diff --git a/libavutil/Makefile b/libavutil/Makefile index 1095c5cfcf..4630e51bbc 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -270,6 +270,7 @@ TESTPROGS = adler32 \ cpu \ crc \ des \ + detection_bbox \ dict \ display \ encryption_info \ diff --git a/libavutil/tests/detection_bbox.c b/libavutil/tests/detection_bbox.c new file mode 100644 index 0000000000..330ed3b7b0 --- /dev/null +++ b/libavutil/tests/detection_bbox.c @@ -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 +#include +#include + +#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; +} diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak index b0df2938e6..0471e94bbc 100644 --- a/tests/fate/libavutil.mak +++ b/tests/fate/libavutil.mak @@ -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) diff --git a/tests/ref/fate/detection_bbox b/tests/ref/fate/detection_bbox new file mode 100644 index 0000000000..36acd15192 --- /dev/null +++ b/tests/ref/fate/detection_bbox @@ -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