Read a Frame of Video

Share your advanced PureBasic knowledge/code with the community.
chris319
Enthusiast
Enthusiast
Posts: 782
Joined: Mon Oct 24, 2005 1:05 pm

Read a Frame of Video

Post by chris319 »

Here is a program which reads a frame of video using ffmpeg and displays it.

As currently configured, the video should be 1280x720 progressive pixels. It has been tested with videos in the YUV color space with 4:2:0 pixels, which most videos are. The program converts YUV to RGB using BT.709 coefficients. You may be able to change this by altering the argument passed to ffmpeg in pipeIn$ and the constats #Kr, #Kg and #Kb.

The program sets up an input pipe from ffmpeg. It was (fairly) easy to do in PureBasic. I hate to think what it's like in other languages.

ffmpeg.exe needs to be available to your program. It could be in the same folder as your program file. ffmpeg executables can be obtained here: https://ffmpeg.zeranoe.com/builds/

Comments welcome.

Code: Select all

; PROGRAM TO READ ONE FRAME OF VIDEO BY chris319
; updated 3/3/2020

#H = 720: #W = 1280

;BT.709 COEFFICIENTS
#Kr = 0.2126: #Kg = 0.7152: #Kb = 0.0722

Global Dim frame.a(#H*#W*3) ;Allocate a buffer To store one frame
Global numpixels = #H * #W

OpenWindow(1,0,0,#W,#H,"")

Procedure RedrawImage()
  StartDrawing(WindowOutput(1))
  DrawImage(ImageID(1),0,0,#W, #H)
  StopDrawing()
EndProcedure

CreateImage(1, #W, #H , 24)

Global filename$ = OpenFileRequester("Select a file","Videos", "Media files (*.avi, *.wmv, *.mp4, *.mp2)"+Chr(0)+"*.avi; *.wmv; *.mp4; *.mp2", 3)

If filename$ = ""
FreeArray(frame())
CloseWindow(1):End
EndIf

filename$ = Chr(34) + filename$ + Chr(34); ENCLOSE FILE NAME IN QUOTATION MARKS

pipeIn$ = "-i " + filename$ + " -f image2pipe  -s 1280x720  -pix_fmt yuv420p  -r 59.94  -vf scale=in_range=limited:out_range=limited,scale=in_color_matrix=bt709,scale=out_color_matrix=bt709  -vcodec rawvideo -"

readFrame = RunProgram("ffmpeg.exe", pipeIn$, "", #PB_Program_Open | #PB_Program_Read)

ReadProgramData(readFrame, @frame(0), #H * #W * 3)

CloseProgram(readFrame)

StartDrawing(ImageOutput(1))
*pntr = @frame.a(0)

For ycoord = 0 To #H - 1
For x = 0 To #W - 1

y.a = PeekA(*pntr)
u.a = frame((yCoord / 2) * (#W / 2) + (x / 2) + numpixels)
v.a = frame((yCoord / 2) * (#W / 2) + (x / 2) + numpixels + (numpixels / 4))

yf.f = y
uf.f = u
vf.f = v

rf.d = (255/219)*yf + (255/112)*vf*(1-#Kr) - (255*16/219 + 255*128/112*(1-#Kr))
gf.d = (255/219)*yf - (255/112)*uf*(1-#Kb)*#Kb/#Kg - (255/112)*vf*(1-#Kr)*#Kr/#Kg - (255*16/219 - 255/112*128*(1-#Kb)*#Kb/#Kg - 255/112*128*(1-#Kr)*#Kr/#Kg)
bf.d = (255/219)*yf + (255/112)*uf*(1-#Kb) - (255*16/219 + 255*128/112*(1-#Kb))

If rf.d > 255: rf = 255: ElseIf rf < 0: rf = 0:EndIf
If gf.d > 255: gf = 255: ElseIf gf < 0: gf = 0:EndIf
If bf.d > 255: bf = 255: ElseIf bf < 0: bf = 0:EndIf

rd.a = rf
gd.a = gf
bd.a = bf

Plot (x, ycoord, RGB(Rd,Gd,Bd)); DRAW COLOR MONITOR

*pntr + 1

Next
Next
StopDrawing()

Repeat: 
event = WaitWindowEvent()
If Event = #PB_Event_Repaint:ReDrawImage():EndIf

Until event = #PB_Event_CloseWindow

FreeArray(frame())
CloseWindow(1):End
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Read a Frame of Video

Post by Mijikai »

Nice, if is there a way to get rgb instead of yuv i think it would be possible to grab and display the buffer at once.
Saboteur
Enthusiast
Enthusiast
Posts: 271
Joined: Fri Apr 25, 2003 7:09 pm
Location: (Madrid) Spain
Contact:

Re: Read a Frame of Video

Post by Saboteur »

Years and years ago..... I asked a universal function for this with no exit.
viewtopic.php?f=3&t=64359

It's not very useful to play movies and can't read frame info and do whatever. I am also a user linux, so there is no easy to solve it.
[:: PB Registered ::]

Win10 Intel core i5-3330 8GB RAM Nvidia GTX 1050Ti
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Read a Frame of Video

Post by Mijikai »

just noticed i posted code for this 2 yrs ago so its possible to grab rgb colors but back then i never tried to use the buffer more directly...
-> https://www.purebasic.fr/german/viewtop ... =2&t=31071
Post Reply