The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

VideoLAN::LibVLC::MediaPlayer - Media Player

VERSION

version 0.06

SYNOPSIS

my $p= VideoLAN::LibVLC->new->new_media_player();
$p->media("FunnyCatVideo.mp4");
$p->play;

DESCRIPTION

This object wraps libvlc_media_player_t. This is the primary object for media playback.

ATTRIBUTES

libvlc

Read-only reference to the library instance that created this player.

media

The VideoLAN::LibVLC::Media object being played

is_playing

Boolean, whether playback is active

will_play

Boolean, whether the media player is able to play

is_seekable

Boolean, whether media is seekable

can_pause

Boolean, whether playback can be paused

rate

The requested playback rate. (multiple or fraction of real-time)

Writing this attribute calls "set_rate".

length

The length in seconds of the media

title_count

Number if subtitle tracks in the media, or undef.

title

Number of the subtitle track currently playing, or undef.

"title" is the official language of libvlc, but "subtitle" is what English speakers probably expect to find. I decided to stick with the API's terminology.

chapter_count

Number of chapters in media, or undef

chapter

Chapter number currently playing, or undef if no media is playing. Setting this attribute changes the chapter.

time

The position within the media file, measured in seconds. Undef until playback begins. Setting this attribute performs a seek.

position

The position within the media file, measured as a fraction of media length. (0..1). Undef until playback begins. Setting this attribute performs a seek.

METHODS

new

my $player= VideoLAN::LibVLC::MediaPlayer->new(
  libvlc => $vlc,
);

set_media

Set the player's active media soruce. May be an instance of VideoLAN::LibVLC::Media or any valid argument for "new_media" in VideoLAN::LibVLC.

This can also be called by setting the "media" attribute.

play

pause

set_pause

Requires libvlc 1.1.1

stop

set_rate

set_video_title_display

$player->set_video_title_display( $position, $timeout );

Specify where and how long subtitles should be displayed. Position is one of:

use VideoLAN::LibVLC ':position_t';
# POSITION_DISABLE
# POSITION_CENTER
# POSITION_LEFT
# POSITION_RIGHT
# POSITION_TOP
# POSITION_TOP_LEFT
# POSITION_TOP_RIGHT
# POSITION_BOTTOM
# POSITION_BOTTOM_LEFT
# POSITION_BOTTOM_RIGHT

but may also be an uppercase or lowercase string of one of those minus the leading "POSITION_".

Timeout is in seconds.

Requires host libvlc 2.1, but only warns if this method is not supported.

VIDEO CALLBACK API

The primary motivation for using LibVLC rather than shelling out to the actual VLC binary is that you can capture the decoded video or audio and do something with it. Here's an overview of how to process the video frames generated by VLC:

Prepare to Dispatch Messages

VLC runs in a separate thread from the main program. In order to handle callbacks, you need to pump a message queue that this module uses to ferry the events back and forth. The most direct way is with

$vlc= $player->libvlc;
while ($main_loop) {
  ...
  # dispatch each pending message
  1 while $vlc->callback_dispatch;
  ...
}

If you are using an event library like AnyEvent, it can simply be

AE::io $vlc->callback_fh, 0, sub { $vlc->callback_dispatch };
Choose Video Format

Decide whether you want to force a specific video format, or use the native format of the media, or a little of both. Using the native format of the media requires VLC 2.0 or higher.

To specify your own format, call set_video_callbacks without the format callback, and then call "set_video_format" with the desired chroma, width, height, and pitch.

$p->set_video_callbacks(display => sub { ... });
$p->set_video_format({ chroma => "RGBA", width => 640, height => 480, pitch => 640*4 });

To adapt to the format of the media (especially for width/height, even if you plan to force RGB or something) set the format callback, and then call "set_video_format" from within that callback. You can also allocate the pictures after setting the format, though you might want to wait for the lock callback since VLC sometimes calls this multiple times before playback begins.

$p->set_video_callbacks(
  format  => sub {
    my ($p, $event)= @_;
    $p->set_video_format({
      chroma => "RGBA",
      width => $event->{width},
      height => $event->{height},
      pitch => $event->{width}*4
    });
  },
  lock => sub {
    # allocate pictures here, if it hasn't been done yet
    # See below.
  }
  display => sub { ... },
);
Create Picture Buffers

Once you know the format, you can create picture buffers for VLC to render into. These are instances of VideoLAN::LibVLC::Picture. If you only specify the dimensions of the picture buffer, it will allocate memory internally. You may also provide the memory of the planes as scalar-refs, but this is likely to crash your program if you're not careful, and should only be done if you have special requirements like rendering into a memory-map (such as created by File::Map or OpenGL::Sandbox::Buffer).

After creating a picture buffer, pass it to queue_picture. This gives the internal VLC thread access to them.

$p->queue_new_picture(id => $_) for 0..7;

# which is shorthand for:

for (0..7) {
  my $pic= VideoLAN::LibVLC::Picture->new( $p->video_format->%*, id => $_ );
  $p->queue_picture($pic);
}

Picture IDs aren't required but it helps when debugging with "trace_pictures".

Handle the Lock and Unlock events

The VLC thread runs asynchronous to the main Perl program. It notifies you when it needs a new buffer, and when it has filled that buffer. These events can be handled with callbacks, if you want. Note that you'll need a really fast turnaround time for the lock callback, and it is much better to queue pictures in advance. But, you can queue in advance and still receive the lock callback for bookkeeping purposes. The unlock callback lets you know when the VLC thread has filled a buffer, but it is not necessarily time to display the buffer. Depending on the video codec, the images might be created in a different order than they get displayed.

Handle the Display event

The most important callback is the display callback. This tells you when it is time to show a picture. This event is also the moment that a Picture object becomes detached from the MediaPlayer object. You need to call "queue_picture" again afterward if you want to recycle the picture.

Handle the Cleanup event

Using the VLC 2.0 API also gives you a cleanup event when VLC is done rendering pictures. The way the API works, you must also use the format callback to be able to use the cleanup callback.

set_video_callbacks

This method sets up the player to render into user-supplied picture buffers. it accepts a hash of callbacks:

format
format => sub {
  my ($player, $event)= @_;
  # event contains all the same attributes as ->set_video_format takes
}

Called (sometimes multiple times) when VLC builds its decoding pipeline.

lock
lock => sub {
  my ($player, $event)= @_;
  ...
  $player->queue_picture(...);
}

Called when the decoding threads wants a new picture. Respond with "queue_pictue", or better, maintain the queue of pictures by checking "queued_picture_count" and queueing them in advance.

unlock
unlock => sub {
  my ($player, $event)= @_;
  # do something with $event->{picture}
}

Called wien the decoding thread has filled a picture, though it might not be the next picture that should be displayed. (this event would mainly be useful to begin syncing the data to somewhere)

display
display => sub {
  my ($player, $event)= @_;
  # do something with $event->{picture}
}

This is called when it is time to show the picture. If you are done displaying the previous picture, now is a good time to recycle it with $player->queue_picture($prev_picture).

cleanup
cleanup => sub { 
  my ($player, $event)= @_;
  ...
}

You can release resources of the pictures here, but the player might still hold references to a few of of the Picture objects.

discard
discard => sub {
  my ($player, $event)= @_;
  ... # free resources of $event->{picture}
}

This is called for any picture which the decoder wasn't able to use, either due being the wrong format, or at the end of playback of there were extra pictures queued.

opaque
opaque => $my_object

Not a callback; this option allows you to specify some other object which will be passed to your callbacks as the first argument, rather than $player.

set_video_format

$p->set_video_format(
  chroma      => "....",   # VLC four-CC code.  required
  width       => $width,   # in pixels.  requird.
  height      => $height,  # in pixels.  required.
  pitch       => \@pitch,  # may also be single value for single-plane images
  lines       => \@lines,  # may also be single value for single-plane images
  alloc_count => $n        # number of concurrent buffers you plan to provide
);

If this is called without registering a format callback, it will call libvlc_video_set_format which forces VLC to rescale the pictures to your desired format. If called after registering a format callback, it will send this as a reply to the video thread, with mostly the same effect (but after you've had the opportunity to see what the native format is).

See VideoLAN::LibVLC::Picture for discussion of the parameters other than alloc_count. alloc_count is the number of pictures you plan to make available to the decoder at one time, and might be used by the decoder to decide whether to allocate its own temporary buffers if it can't get enough supplied by the application.

If you are using the format callback, this should only be called in response to the callback. You should also set $alloc_count, and $lines[0..2] and $pitch[0..2].

If not using the callback, this should only be called once, and $lines and $alloc_count and <$pitch[1..2]> are ignored due to limitations of the older API.

new_picture

my $picture= $player->new_picture( %overrides );

Retun a new VideoLAN::LibVLC::Picture object, defaulting to the format last registered with "set_video_format". Any arguments to this function will be merged with those format parameters.

queue_picture

$player->queue_picture($picture);

Push a picture onto the queue to the VLC decoding thread. Once pushed, you may not alter the picture in any way, or else risk crashing your program. It is best to drop any reference you had to the picture and let the Player hold onto it until time for a display event.

queue_new_picture

A shorthand combination of the above methods.

queued_picture_count

Number of pictures which have been given to the decoder thread and have not yet come back for display. This does include pictures which have been seen by the "unlock" callback.

trace_pictures

This is an attribute of the player that, when enabled, causes all exchange of pictures to be logged on file descriptor 2 (stderr). Note that due to the multi-threaded nature of the VLC decoder, this won't be synchronized with changes to STDERR by perl, and could result in garbled messages in some cases. This is only intended for debugging use.

AUDIO CALLBACK API (TODO)

I have not implemented this yet. Patches welcome.

AUTHOR

Michael Conrad <mike@nrdvana.net>

COPYRIGHT AND LICENSE

This software is copyright (c) 2023 by Michael Conrad.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.