Dmitriy Kozlov
Dmitriy Kozlov

Reputation: 299

Showing YUV420p using pygame overlay leads to green bar on top of image

The code is as follows. Image is decoded by PyAV library. On top of picture there is a horizontal green bar. Probably 1 pixel height. Do you have any idea how to avoid that? I have seen lots of recomendations for VLC player to disable hardware acceleration. It is already disabled in pygame. I work in Windows10 64bit.

import av
import pygame
import time

container = av.open('video.mp4') # libx264 en-/decoded, pixel format yuv420p
container.streams.video[0].thread_type = 'AUTO'
frameSequence = container.decode(video=0)
for _ in range(100):
    image = next(frameSequence) #skip some frames
pygame.init()
trueResolution = pygame.display.list_modes()[0]  # corresponds to video, as it FULL HD
                                                 #also tested with HD
pygame.display.set_mode(trueResolution)
ovl = pygame.Overlay(pygame.YV12_OVERLAY,trueResolution)
ovl.display((image.planes[0], image.planes[1], image.planes[2]))
time.sleep(10)

I have also tried to replace first lines in every plane by other lines, to check whether the image is corrupted. Results are the same, so the image seems to be correct.

UPD1. The link to video https://drive.google.com/file/d/1t6d5weBVeW4EWzGI1gytmUBwXF91dNC9/view?usp=sharing

The screenshot with a green line on top of the image The screenshot with a green line on top of the image

Upvotes: 1

Views: 285

Answers (1)

import random
import random

Reputation: 3245

You can reduce to screen size and change the location of the overlay to hide the green bars. I know this is not a fix, but you might find it good enough to progress further.

The documentation for Overlay does warn:

The Overlay objects represent lower level access to the display hardware. To use the object you must understand the technical details of video overlays.

So someone with more domain expertise might be able to provide a better solution.

pygame.display.set_mode((1280,  718), pygame.RESIZABLE)
ovl = pygame.Overlay(pygame.YV12_OVERLAY,trueResolution)
ovl.set_location(pygame.Rect(0,-2,1280, 720))

Note also trueResolution should be determined from the source stream rather than the full screen modes supported by the graphics card.

Also the image in this case is a VideoFrame, you can use its .to_image() method to convert to a PIL type image or .to_rgb(), which might be easier to display if you don't want/need to use an Overlay.

Upvotes: 1

Related Questions