strukturag / libheif

libheif is an HEIF and AVIF file format decoder and encoder.
Other
1.77k stars 306 forks source link

cpu surge #1385

Closed styst closed 1 week ago

styst commented 1 week ago

In version 1.19.3, when using heif-convert to convert JPG images on a multi-core CPU server, there is an occasional occurrence of CPU spikes (possibly due to the simultaneous submission of multiple images by the user)

The conversion of the image is showing progress in the middle, whereas previously it would directly reach 100%. 39MHGAEbeW

styst commented 1 week ago

insert another error: Could not read HEIF/AVIF file: Memory allocation error: Security limit exceeded: Maximum number of child boxes (100) in 'ipco' box exceeded.

farindk commented 1 week ago

The conversion of the image is showing progress in the middle, whereas previously it would directly reach 100%.

The only difference to the previous version is that it is now showing a progress indicator, while it previously did not output any progress information. If that is spamming your logs, I can add a 'quite' option to disable the progress output.

insert another error: Could not read HEIF/AVIF file: Memory allocation error: Security limit exceeded: Maximum number of child boxes (100) in 'ipco' box exceeded.

It's not and error, it is a security limit that tries to prevent DoS attacks. Usually, an ipco box as <10 items, but your image seems to have >100 items. You can call heif-dec with --disable-limits, but then a malicious input file might be used for DoS attacks. Can you send me the file that exceeded the security limit? I can also send you an upload link if you do not want to share it publicly.

styst commented 1 week ago

From what I see here, it seems that the high CPU usage up to 90% is caused by slow execution of instructions, not an issue with output any progress information

styst commented 1 week ago

This image was uploaded by the user, but it failed, so I didn't save it either. I am currently trying to ask the user for it, but I'm not sure if I will be able to obtain it.

styst commented 1 week ago

Does converting multiple images at the same time make it slow?

farindk commented 1 week ago

HEIF is simply more computationally complex than JPEG. One solution might be to offload most of the decoding work to the hardware decoders on the GPU, but this is not implemented yet in libheif.

styst commented 1 week ago

So, this issue is not caused by the changes in the new version 1.19.3, is it? The reason why I have doubts is because this problem occurred after I switched to the new version 1.19.3 yesterday; it never happened before.

farindk commented 1 week ago

v1.19.3 should never be slower. In many cases, e.g. HEIC to JPEG it should even be faster. If you have an image for which this is not the case, please send it to me so that I can check it.

styst commented 1 week ago

The scene at that time was not preserved, so I reverted the version to 1.18 and adjusted the container to 1-core CPU. Just now, after a picture was converted, a green color block appeared. You can reproduce if you like. The color block occurred when using a single-core CPU. Please provide me with an address to upload the picture, and I will send that picture over.

farindk commented 1 week ago

upload link: https://cloud.dirk-farin.de/s/YWiPLotrNerqnGc

styst commented 1 week ago

I have uploaded two pictures, one before conversion and one after conversion.

farindk commented 1 week ago

I have measured the time converting a dataset of 1500 HEIC images to JPEG:

styst commented 1 week ago

Understood... The CPU surge issue that occurred today was not caused by the new version.

styst commented 1 week ago

Is the image used in the above experiment the one I uploaded? Did the results differ after the conversion?

farindk commented 1 week ago

I've now tested your uploaded image. As expected, the green block (race condition) may happen for versions v1.19.0 - v1.19.2. I never got a wrong output for v1.18.2 or v1.19.3.

styst commented 1 week ago

OK,Can you remove the any progress information? Let me try again because I have a while loop here that reads every line of the output, which may affect performance.

farindk commented 1 week ago

I have already removed it in the commit above (2a764da6053f08b472f7127f8d95772e64ef015a). Use the master branch and use the --quiet option.

styst commented 1 week ago

Thank you.I will try it.

styst commented 1 week ago

I have discovered a new issue, after converting this image to .jpg format using version v.1.19.3, the "Orientation" tag in the EXIF metadata, which indicates the photo's shooting angle information., has changed to: right side, top (Rotate 90 CW), which led me to rotate the image based on this incorrect information. I have uploaded this image to the URL you provided, with the name "1ea7838f1d486c7705397ad0e70d0c39.webp".

farindk commented 1 week ago

I have discovered a new issue, after converting this image to .jpg format using version v.1.19.3, the "Orientation" tag

I get:

$ exiftool 1ea7838f1d486c7705397ad0e70d0c39.heic |grep Orientation
Orientation                     : Rotate 90 CW

$ heif-info 1ea7838f1d486c7705397ad0e70d0c39.heic 
...
transformations:
  angle (ccw): 270
...

$ heif-dec 1ea7838f1d486c7705397ad0e70d0c39.heic -o out.jpg
File contains 1 image
decoding image... 100%
Written to out.jpg

$ exiftool out.jpg |grep Orientation
Orientation                     : Horizontal (normal)

The input HEIC also has an irot of 270 degrees, matching the EXIF.

The output of heif-dec is correct. In HEIF, the EXIF Orientation is only informal, the relevant information is in irot. During the conversion, libheif normalizes the orientation and outputs the image in the normal orientation. Thus, it also changes the Orientation in the JPEG EXIF to "normal" because in JPEG the Orientation in the EXIF is to be handled by the client application.

This is a common misunderstanding how EXIF works with HEIC. Search in the issues, you will find that many times...