First I like libVLC I can get all pixels from any video media (file, DVD, network stream, USB camera ...)
But there is one issue with this fine free library.
To get decoded video frames as FBImage or directly to the FBGFX screen
you must setup the pixel format and size of the media where you like to grab the pixels from
then you have to setup some callbacks to get the decoded frames
than you are ready to play the media ...
This worlks without any problems but wait
how do you setup the size (before you can play) if you don't know the resolution ?
So far I know before the player begins to play (decoding the first frame)
there isn't a way to get the resolution from the media object !
So you have to setup a format callback and create a dummy player instance.
Than you start playing and the format callback are called and we got the size of the video.
Now we can stop the dummy player and release it.
After we got width and height of the media we can create a FBGFX screen or an fb image for the rendering.
Joshy
here are the right steps:
Code: Select all
#include once "vlc/vlc.bi"
dim shared as integer frame
dim shared as long pause,videoW,videoH,gotFormat
' we need this callback to get the dimension of the media !?!
function formatCB cdecl(byval userdata as any ptr ptr, _
byval chroma as zstring ptr, _
byval w as ulong ptr, _
byval h as ulong ptr, _
byval pitches as ulong ptr, _
byval lines as ulong ptr) as long
videoW=*w : videoH=*h : gotFormat=1
return 0
end function
function lockCB cdecl (byval image as any ptr, byval pPlanes as any ptr ptr) as any ptr
if (image=0) then ' we use the the FBGFX screen as target so we must lock it
screenlock : pPlanes[0]=screenptr() ' get the address of the screen pixel buffer
else ' we use any RGB image get the address of the pixel buffer
Imageinfo(image,,,,,pPlanes[0])
end if
return 0
end function
sub unlockCB cdecl (byval image as any ptr, byval pPicture as any ptr, byval pPlanes as any const ptr ptr)
if (image=0) then screenunlock ' if we use the FBGFX screen we must unlock it
end sub
sub displayCB cdecl (byval image as any ptr, byval pPicture as any ptr)
' ignore it in pause mode
if pause then return
' count the new frame
frame+=1
' if we use the screen all rendering are done and we can go out here
if (image=0) then return
' use the decoded image for what ever you need here
' I blit it on screen
put (0,0),image,PSET
end sub
'
' main
'
' set your video url here
dim as zstring ptr VIDEO = @"./HAL_9000_I_m_sorry_Dave_I_m_afraid_I_can_t_do_that.mp4"
' this image or the screen becomes the target of the video decoder
dim as any ptr image
' in my test case the video are in the same folder as the exe
chdir exepath()
' I don't like the debug output of libVLC so I try to disable them
SetEnviron "VLC_VERBOSE=-1"
' init the lib
var instance = libvlc_new (0,NULL)
' create the media object from path/url
var media = libvlc_media_new_path(instance, VIDEO)
' create a player onyl to get the format of the video !!!
var player = libvlc_media_player_new_from_media(media)
' set the callback to retreive the format
libvlc_video_set_format_callbacks(player,@formatCB,0)
' to enable the formatCB we have to setup the other callbacks also
libvlc_video_set_callbacks(player, @lockCB, @unlockCB, @displayCB, image)
' start the player to get the video resolution
var result = libvlc_media_player_play(player)
if (result<>0) then
print "error: play get format ! ..."
libvlc_media_player_release(player)
libvlc_release(instance)
beep : sleep : end 2
end if
' we must wait for the FormatCB here
while gotFormat=0 andalso inkey()=""
sleep 10
wend
' now we got the video resolution and we can strop and relase our dummy player :-)
libvlc_media_player_stop(player) : sleep 500,1 ' give it a litle bit time to stop
libvlc_media_player_release(player) ' release it
' here I use the half of the size (why not)
dim as integer SCR_W=videoW\2
dim as integer SCR_H=videoH\2
screenres SCR_W,SCR_H,32
' we use an image here (if you comment it out the screen will be used)
image=imagecreate(SCR_W, SCR_H)
dim as integer frameW,frameH,frameP
if image=0 then ' we use the screen get current size and pitch
screeninfo frameW,frameH,,,frameP
else ' we use an image get size and pitch from image
imageinfo image,frameW,frameH,,frameP
end if
' now we have to create a new player object to play the video
player = libvlc_media_player_new_from_media(media)
' set our format (from screen or image)
libvlc_video_set_format(player,@"BGRA", frameW, frameH, frameP)
' set the decoder callbacks
libvlc_video_set_callbacks(player, @lockCB, @unlockCB, @displayCB, image)
' start to play
result = libvlc_media_player_play(player)
if (result<>0) then
print "error: can't play ! ..."
libvlc_media_player_release(player)
libvlc_release(instance)
beep : sleep : end 2
end if
' only for testing: get time of the media in ms
'var milliseconds = libvlc_media_get_duration(media)
'while milliseconds=-1 andalso inkey()=""
' windowtitle "warning: can't get duration of the media !"
' sleep 10 ' don't eat all CPU cycles here
' milliseconds = libvlc_media_get_duration(media)
'wend
'windowtitle "seconds: " & milliseconds/1000
' we not longer need the media
libvlc_media_release(media)
'result = libvlc_media_player_will_play(player)
'while result=0
' beep
' result = libvlc_media_player_will_play(player)
'wend
' optionmal set the audio volume 0-100%
libvlc_audio_set_volume(player,100)
dim as libvlc_state_t PlayerState
var key=asc(inkey())
' play the the video or press [ESCAPE] to interrupt
while key<>27 and (PlayerState<>libvlc_Ended)
' only for testing press space to togle the pause mode
if key=32 then pause=1-pause : libvlc_media_player_set_pause(player,pause)
' get the curreent state of the player
PlayerState = libvlc_media_player_get_state(player)
windowtitle "frame: " & frame & " player state: " & iif(PlayerState=3,"playing ...",iif(PlayerState=4,"paused ...","ended"))
key=asc(inkey())
sleep 100
wend
' if the vide was interrupted stop it manualy
if (PlayerState<>libvlc_Ended) then libvlc_media_player_stop(player) : sleep 500,1 ' give it a bit time to end all callbacks
' free it
libvlc_media_player_release(player)
' close it
libvlc_release(instance)