UAV-Pilot-SDL
view release on metacpan or search on metacpan
lib/UAV/Pilot/SDL/Video.pm view on Meta::CPAN
},
);
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
lib/UAV/Pilot/SDL/Video.pm view on Meta::CPAN
$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;
lib/UAV/Pilot/SDL/Video.pm view on Meta::CPAN
$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
lib/UAV/Pilot/SDL/Video.xs view on Meta::CPAN
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <SDL/SDL.h>
MODULE = UAV::Pilot::SDL::Video PACKAGE = UAV::Pilot::SDL::Video
void
_draw_last_video_frame( self, overlay, dstrect, frame_sv)
SV* self
SDL_Overlay* overlay
SDL_Rect* dstrect
SV* frame_sv
PPCODE:
AVFrame* frame = (AVFrame*) SvIV( frame_sv );
AVPicture pict;
struct SwsContext * sws_context = sws_getContext(
dstrect->w,
dstrect->h,
UAV_PIX_FMT,
dstrect->w,
lib/UAV/Pilot/SDL/Video.xs view on Meta::CPAN
NULL,
NULL
);
if( sws_context == NULL ) {
warn( "Could not get SWS context\n" );
exit( 1 );
}
SDL_LockYUVOverlay( overlay );
// Data comes from YUV420P source; U and V arrays swapped
pict.data[0] = overlay->pixels[0];
pict.data[1] = overlay->pixels[2];
pict.data[2] = overlay->pixels[1];
pict.linesize[0] = overlay->pitches[0];
pict.linesize[1] = overlay->pitches[2];
pict.linesize[2] = overlay->pitches[1];
sws_scale( sws_context, (const uint8_t * const *) frame->data,
frame->linesize, 0, dstrect->h, pict.data, pict.linesize );
SDL_UnlockYUVOverlay( overlay );
SDL_DisplayYUVOverlay( overlay, dstrect );
sws_freeContext( sws_context );
lib/UAV/Pilot/SDL/VideoOverlay.pm view on Meta::CPAN
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# 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::VideoOverlay;
use v5.14;
use Moose::Role;
requires 'process_video_overlay';
has 'video_overlay' => (
is => 'ro',
isa => 'Maybe[UAV::Pilot::SDL::Video]',
writer => '_set_video_overlay',
);
sub init_video_overlay
{
my ($self, $video) = @_;
$self->_set_video_overlay( $video );
return 1;
}
1;
__END__
=head1 NAME
UAV::Pilot::SDL::VideoOverlay
=head1 DESCRIPTION
A role for objects to draw on top of a video. Requires a
C<process_video_overlay()> method, which will be passed the C<UAV::Pilot::SDL::Window> object that the video is drawing to.
Where C<$video> is an C<UAV::Pilot::SDL::Video> object, you can set an
C<$overlay> object with:
$video->register_video_overlay( $overlay );
B<NOTE>: This is still experimental. Lines tend to flicker and show up as
black. This is probably due to the SDL YUV hardware overlay.
=cut
lib/UAV/Pilot/SDL/VideoOverlay/Reticle.pm view on Meta::CPAN
use constant RETICLE_HALF_SIZE_PERCENT => 0.1; # Takes up x percent of screen size
with 'UAV::Pilot::SDL::VideoOverlay';
has 'reticle_color' => (
is => 'ro',
writer => '_set_reticle_color',
);
after 'init_video_overlay' => sub {
my ($self, $video, $window) = @_;
my $sdl = $window->sdl;
my @color_parts = @{ $self->RETICLE_COLOR };
my $reticle_color = SDL::Video::map_RGB( $sdl->format, @color_parts );
$self->_set_reticle_color( $reticle_color );
return 1;
};
sub process_video_overlay
{
my ($self, $window) = @_;
my $sdl = $window->sdl;
my $reticle_color = $self->reticle_color;
my $half_size_percent = $self->RETICLE_HALF_SIZE_PERCENT;
# TODO this needs to be based on the rect that the Video is being drawn on
my $w = $sdl->w;
my $h = $sdl->h;
my $center_x = int( $w / 2 );
my $center_y = int( $h / 2 );
lib/UAV/Pilot/SDL/Window.pm view on Meta::CPAN
has 'children' => (
traits => ['Array'],
is => 'ro',
isa => 'ArrayRef[HashRef[Item]]',
default => sub {[]},
handles => {
'_add_child' => 'push',
'_has_no_children' => 'is_empty',
},
);
has 'yuv_overlay' => (
is => 'ro',
isa => 'Maybe[SDL::Overlay]',
writer => '_set_yuv_overlay',
);
has 'yuv_overlay_rect' => (
is => 'ro',
isa => 'Maybe[SDL::Rect]',
writer => '_set_yuv_overlay_rect',
);
has 'width' => (
is => 'ro',
isa => 'Int',
default => 0,
writer => '_set_width',
);
has 'height' => (
is => 'ro',
isa => 'Int',
lib/UAV/Pilot/SDL/Window.pm view on Meta::CPAN
$self->_resize( $new_width, $new_height );
$self->_add_child({
origin_x => $x,
origin_y => $y,
drawer => $child,
});
return 1;
}
sub add_child_with_yuv_overlay
{
my ($self, $child, $overlay_flag, $float) = @_;
$float //= $self->TOP;
my $width = $child->width;
my $height = $child->height;
my ($x, $y, $new_width, $new_height) = $self->_calc_new_child(
$child, $float );
my $sdl = $self->sdl;
my $overlay = SDL::Overlay->new( $width, $height, $overlay_flag, $sdl );
my $overlay_rect = SDL::Rect->new( $x, $y, $width, $height );
$self->_set_yuv_overlay( $overlay );
$self->_set_yuv_overlay_rect( $overlay_rect );
$self->_resize( $new_width, $new_height );
$self->_add_child({
origin_x => $x,
origin_y => $y,
drawer => $child,
});
return 1;
}
lib/UAV/Pilot/SDL/Window.pm view on Meta::CPAN
=head1 METHODS
=head2 add_child
add_child( $handler, $float ).
Pass a child that does the C<UAV::Pilot::SDL::WindowEventHandler> role.
Float should be C<<$window->TOP>> or C<<$window->BOTTOM>> for the location to
draw this child. The window will be expanded to fit the child's width/height.
=head2 add_child_with_yuv_overlay
add_child_with_yuv_overlay( $handle, $overlay_flag, $float )
Pass a child that does the C<UAV::Pilot::SDL::WindowEventHandler> role. The
C<$overlay_flag> will be the flag passed to C<SDL::Overlay> (see that module's
docs for details). The C<$float> param is the same as C<add_child()>.
=head2 sdl
Returns the C<SDLx::App> object for the given SDL window.
=head2 yuv_overlay
If a child was added with C<add_child_with_yuv_overlay()>, returns the
C<SDL::Overlay> object.
=head2 yuv_overlay_rect
If a child was added with C<add_child_with_yuv_overlay()>, returns an
C<SDL::Rect> object that covers the overlay area.
=head1 DRAWING METHODS
The should only be used by widgets when their C<draw()> method is called.
All C<$x, $y> coordinates are relative to the widgets's drawing area.
=head2 clear_screen
Blanks the area that the current widget is being drawn in.
( run in 0.251 second using v1.01-cache-2.11-cpan-65fba6d93b7 )