tests/fate/libavutil: add FATE test for detection_bbox

Unit test covering av_detection_bbox_alloc, av_get_detection_bbox,
and av_detection_bbox_create_side_data.

Tests allocation with 0, 1, and 4 bounding boxes, with and without
size output. Verifies bbox getter indexing by writing and reading
back coordinates, labels, and confidence values. Tests classify
fields (labels and confidences), the header source field, and
side data creation with frame attachment.

Coverage for libavutil/detection_bbox.c: 0.00% -> 86.67%
(remaining uncovered lines are OOM error paths)

Signed-off-by: marcos ashton <marcosashiglesias@gmail.com>
This commit is contained in:
marcos ashton
2026-03-25 23:10:45 +00:00
parent be2fa77344
commit c8ec660d78
4 changed files with 159 additions and 0 deletions

View File

@@ -270,6 +270,7 @@ TESTPROGS = adler32 \
cpu \
crc \
des \
detection_bbox \
dict \
display \
encryption_info \

View File

@@ -0,0 +1,132 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "libavutil/detection_bbox.h"
#include "libavutil/frame.h"
#include "libavutil/macros.h"
#include "libavutil/mem.h"
int main(void)
{
AVDetectionBBoxHeader *header;
AVDetectionBBox *bbox;
AVFrame *frame;
size_t size;
static const unsigned int alloc_counts[] = { 0, 1, 4 };
/* av_detection_bbox_alloc - various counts */
printf("Testing av_detection_bbox_alloc()\n");
for (int i = 0; i < FF_ARRAY_ELEMS(alloc_counts); i++) {
unsigned int nb = alloc_counts[i];
header = av_detection_bbox_alloc(nb, &size);
if (header) {
printf("alloc %u: OK, nb=%u, size>0=%s\n",
nb, header->nb_bboxes, size > 0 ? "yes" : "no");
av_free(header);
} else {
printf("alloc %u: FAIL\n", nb);
}
}
/* av_detection_bbox_alloc without size */
header = av_detection_bbox_alloc(1, NULL);
printf("alloc (no size): %s\n", header ? "OK" : "FAIL");
av_free(header);
/* av_get_detection_bbox - pointer consistency and write/read back */
printf("\nTesting av_get_detection_bbox()\n");
header = av_detection_bbox_alloc(3, NULL);
if (header) {
for (int i = 0; i < 3; i++) {
bbox = av_get_detection_bbox(header, i);
if ((uint8_t *)bbox != (uint8_t *)header + header->bboxes_offset +
(size_t)i * header->bbox_size)
printf("bbox %d: pointer inconsistent with bboxes_offset/bbox_size\n", i);
bbox->x = i * 100;
bbox->y = i * 200;
bbox->w = 50 + i;
bbox->h = 60 + i;
snprintf(bbox->detect_label, sizeof(bbox->detect_label),
"obj%d", i);
bbox->detect_confidence = (AVRational){ 90 + i, 100 };
}
for (int i = 0; i < 3; i++) {
bbox = av_get_detection_bbox(header, i);
printf("bbox %d: x=%d y=%d w=%d h=%d label=%s conf=%d/%d\n",
i, bbox->x, bbox->y, bbox->w, bbox->h,
bbox->detect_label,
bbox->detect_confidence.num,
bbox->detect_confidence.den);
}
av_free(header);
}
/* classify fields */
printf("\nTesting classify fields\n");
header = av_detection_bbox_alloc(1, NULL);
if (header) {
bbox = av_get_detection_bbox(header, 0);
bbox->classify_count = 2;
snprintf(bbox->classify_labels[0], sizeof(bbox->classify_labels[0]),
"cat");
bbox->classify_confidences[0] = (AVRational){ 95, 100 };
snprintf(bbox->classify_labels[1], sizeof(bbox->classify_labels[1]),
"animal");
bbox->classify_confidences[1] = (AVRational){ 80, 100 };
printf("classify_count=%u\n", bbox->classify_count);
for (int i = 0; i < (int)bbox->classify_count; i++)
printf("classify %d: %s %d/%d\n", i,
bbox->classify_labels[i],
bbox->classify_confidences[i].num,
bbox->classify_confidences[i].den);
av_free(header);
}
/* header source field */
printf("\nTesting source field\n");
header = av_detection_bbox_alloc(1, NULL);
if (header) {
snprintf(header->source, sizeof(header->source), "test_model_v1");
printf("source: %s\n", header->source);
av_free(header);
}
/* av_detection_bbox_create_side_data */
printf("\nTesting av_detection_bbox_create_side_data()\n");
frame = av_frame_alloc();
if (frame) {
header = av_detection_bbox_create_side_data(frame, 2);
if (header) {
printf("side_data: OK, nb=%u\n", header->nb_bboxes);
bbox = av_get_detection_bbox(header, 0);
bbox->x = 10;
bbox->y = 20;
printf("side_data bbox 0: x=%d y=%d\n", bbox->x, bbox->y);
} else {
printf("side_data: FAIL\n");
}
av_frame_free(&frame);
}
return 0;
}

View File

@@ -70,6 +70,10 @@ fate-des: libavutil/tests/des$(EXESUF)
fate-des: CMD = run libavutil/tests/des$(EXESUF)
fate-des: CMP = null
FATE_LIBAVUTIL += fate-detection_bbox
fate-detection_bbox: libavutil/tests/detection_bbox$(EXESUF)
fate-detection_bbox: CMD = run libavutil/tests/detection_bbox$(EXESUF)
FATE_LIBAVUTIL += fate-dict
fate-dict: libavutil/tests/dict$(EXESUF)
fate-dict: CMD = run libavutil/tests/dict$(EXESUF)

View File

@@ -0,0 +1,22 @@
Testing av_detection_bbox_alloc()
alloc 0: OK, nb=0, size>0=yes
alloc 1: OK, nb=1, size>0=yes
alloc 4: OK, nb=4, size>0=yes
alloc (no size): OK
Testing av_get_detection_bbox()
bbox 0: x=0 y=0 w=50 h=60 label=obj0 conf=90/100
bbox 1: x=100 y=200 w=51 h=61 label=obj1 conf=91/100
bbox 2: x=200 y=400 w=52 h=62 label=obj2 conf=92/100
Testing classify fields
classify_count=2
classify 0: cat 95/100
classify 1: animal 80/100
Testing source field
source: test_model_v1
Testing av_detection_bbox_create_side_data()
side_data: OK, nb=2
side_data bbox 0: x=10 y=20