From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Subject: [FFmpeg-devel] [PATCH 4/7] avformat/vvc: Fix crash on allocation failure, avoid allocations
Date: Wed, 5 Jun 2024 13:40:24 +0200
Message-ID: <GV1P250MB0737382DBD7B140F7AB307FE8FF92@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <GV1P250MB0737844821276428E60BD79F8FF92@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM>
This is the VVC version of 8b5d15530127fea54e934043a64653859de07353.
(Hint: This ensures that the order of NALU arrays is OPI-VPS-SPS-PPS-
Prefix-SEI-Suffix-SEI, regardless of the order in the original
extradata. I hope this is right.)
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavformat/vvc.c | 169 ++++++++++++++++++++--------------------------
1 file changed, 73 insertions(+), 96 deletions(-)
diff --git a/libavformat/vvc.c b/libavformat/vvc.c
index 679bb07a4d..819ee02e2c 100644
--- a/libavformat/vvc.c
+++ b/libavformat/vvc.c
@@ -32,6 +32,16 @@
#include "avio_internal.h"
#include "vvc.h"
+enum {
+ OPI_INDEX,
+ VPS_INDEX,
+ SPS_INDEX,
+ PPS_INDEX,
+ SEI_PREFIX_INDEX,
+ SEI_SUFFIX_INDEX,
+ NB_ARRAYS
+};
+
typedef struct VVCCNALUnitArray {
uint8_t array_completeness;
uint8_t NAL_unit_type;
@@ -67,7 +77,7 @@ typedef struct VVCDecoderConfigurationRecord {
uint16_t max_picture_height;
uint16_t avg_frame_rate;
uint8_t num_of_arrays;
- VVCCNALUnitArray *array;
+ VVCCNALUnitArray arrays[NB_ARRAYS];
} VVCDecoderConfigurationRecord;
static void vvcc_update_ptl(VVCDecoderConfigurationRecord *vvcc,
@@ -432,32 +442,11 @@ static void nal_unit_parse_header(GetBitContext *gb, uint8_t *nal_type)
static int vvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
uint8_t nal_type, int ps_array_completeness,
- VVCDecoderConfigurationRecord *vvcc)
+ VVCCNALUnitArray *array)
{
int ret;
- uint8_t index;
uint16_t num_nalus;
- VVCCNALUnitArray *array;
-
- for (index = 0; index < vvcc->num_of_arrays; index++)
- if (vvcc->array[index].NAL_unit_type == nal_type)
- break;
-
- if (index >= vvcc->num_of_arrays) {
- uint8_t i;
-
- ret =
- av_reallocp_array(&vvcc->array, index + 1,
- sizeof(VVCCNALUnitArray));
- if (ret < 0)
- return ret;
-
- for (i = vvcc->num_of_arrays; i <= index; i++)
- memset(&vvcc->array[i], 0, sizeof(VVCCNALUnitArray));
- vvcc->num_of_arrays = index + 1;
- }
- array = &vvcc->array[index];
num_nalus = array->num_nalus;
ret = av_reallocp_array(&array->nal_unit, num_nalus + 1, sizeof(uint8_t *));
@@ -504,7 +493,8 @@ static int vvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
static int vvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
int ps_array_completeness,
- VVCDecoderConfigurationRecord *vvcc)
+ VVCDecoderConfigurationRecord *vvcc,
+ unsigned array_idx)
{
int ret = 0;
GetBitContext gbc;
@@ -529,18 +519,15 @@ static int vvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
* vvcc. Perhaps the SEI playload type should be checked
* and non-declarative SEI messages discarded?
*/
- switch (nal_type) {
- case VVC_OPI_NUT:
- case VVC_VPS_NUT:
- case VVC_SPS_NUT:
- case VVC_PPS_NUT:
- case VVC_PREFIX_SEI_NUT:
- case VVC_SUFFIX_SEI_NUT:
- ret = vvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
- ps_array_completeness, vvcc);
- if (ret < 0)
- goto end;
- else if (nal_type == VVC_VPS_NUT)
+ ret = vvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
+ ps_array_completeness,
+ &vvcc->arrays[array_idx]);
+ if (ret < 0)
+ goto end;
+ if (vvcc->arrays[array_idx].num_nalus == 1)
+ vvcc->num_of_arrays++;
+
+ if (nal_type == VVC_VPS_NUT)
ret = vvcc_parse_vps(&gbc, vvcc);
else if (nal_type == VVC_SPS_NUT)
ret = vvcc_parse_sps(&gbc, vvcc);
@@ -551,11 +538,6 @@ static int vvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
}
if (ret < 0)
goto end;
- break;
- default:
- ret = AVERROR_INVALIDDATA;
- goto end;
- }
end:
av_free(rbsp_buf);
@@ -572,22 +554,21 @@ static void vvcc_init(VVCDecoderConfigurationRecord *vvcc)
static void vvcc_close(VVCDecoderConfigurationRecord *vvcc)
{
- uint8_t i;
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(vvcc->arrays); i++) {
+ VVCCNALUnitArray *const array = &vvcc->arrays[i];
- for (i = 0; i < vvcc->num_of_arrays; i++) {
- vvcc->array[i].num_nalus = 0;
- av_freep(&vvcc->array[i].nal_unit);
- av_freep(&vvcc->array[i].nal_unit_length);
+ array->num_nalus = 0;
+ av_freep(&array->nal_unit);
+ av_freep(&array->nal_unit_length);
}
vvcc->num_of_arrays = 0;
- av_freep(&vvcc->array);
}
static int vvcc_write(AVIOContext *pb, VVCDecoderConfigurationRecord *vvcc)
{
uint8_t i;
- uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0;
+ uint16_t vps_count = 0, sps_count = 0, pps_count = 0;
/*
* It's unclear how to properly compute these fields, so
* let's always set them to values meaning 'unspecified'.
@@ -672,40 +653,33 @@ static int vvcc_write(AVIOContext *pb, VVCDecoderConfigurationRecord *vvcc)
av_log(NULL, AV_LOG_TRACE,
"num_of_arrays: %" PRIu8 "\n",
vvcc->num_of_arrays);
- for (i = 0; i < vvcc->num_of_arrays; i++) {
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(vvcc->arrays); i++) {
+ const VVCCNALUnitArray *const array = &vvcc->arrays[i];
+
+ if (array->num_nalus == 0)
+ continue;
+
av_log(NULL, AV_LOG_TRACE,
- "array_completeness[%" PRIu8 "]: %" PRIu8 "\n", i,
- vvcc->array[i].array_completeness);
+ "array_completeness[%u]: %" PRIu8 "\n", i,
+ array->array_completeness);
av_log(NULL, AV_LOG_TRACE,
- "NAL_unit_type[%" PRIu8 "]: %" PRIu8 "\n", i,
- vvcc->array[i].NAL_unit_type);
+ "NAL_unit_type[%u]: %" PRIu8 "\n", i,
+ array->NAL_unit_type);
av_log(NULL, AV_LOG_TRACE,
- "num_nalus[%" PRIu8 "]: %" PRIu16 "\n", i,
- vvcc->array[i].num_nalus);
- for (j = 0; j < vvcc->array[i].num_nalus; j++)
+ "num_nalus[%u]: %" PRIu16 "\n", i,
+ array->num_nalus);
+ for (unsigned j = 0; j < array->num_nalus; j++)
av_log(NULL, AV_LOG_TRACE,
- "nal_unit_length[%" PRIu8 "][%" PRIu16 "]: %"
- PRIu16 "\n", i, j, vvcc->array[i].nal_unit_length[j]);
+ "nal_unit_length[%u][%u]: %"
+ PRIu16 "\n", i, j, array->nal_unit_length[j]);
}
/*
* We need at least one of each: VPS and SPS.
*/
- for (i = 0; i < vvcc->num_of_arrays; i++)
- switch (vvcc->array[i].NAL_unit_type) {
- case VVC_VPS_NUT:
- vps_count += vvcc->array[i].num_nalus;
- break;
- case VVC_SPS_NUT:
- sps_count += vvcc->array[i].num_nalus;
- break;
- case VVC_PPS_NUT:
- pps_count += vvcc->array[i].num_nalus;
- break;
- default:
- break;
- }
-
+ vps_count = vvcc->arrays[VPS_INDEX].num_nalus;
+ sps_count = vvcc->arrays[SPS_INDEX].num_nalus;
+ pps_count = vvcc->arrays[PPS_INDEX].num_nalus;
if (vps_count > VVC_MAX_VPS_COUNT)
return AVERROR_INVALIDDATA;
if (!sps_count || sps_count > VVC_MAX_SPS_COUNT)
@@ -804,25 +778,29 @@ static int vvcc_write(AVIOContext *pb, VVCDecoderConfigurationRecord *vvcc)
/* unsigned int(8) num_of_arrays; */
avio_w8(pb, vvcc->num_of_arrays);
- for (i = 0; i < vvcc->num_of_arrays; i++) {
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(vvcc->arrays); i++) {
+ const VVCCNALUnitArray *const array = &vvcc->arrays[i];
+
+ if (!array->num_nalus)
+ continue;
/*
* bit(1) array_completeness;
* unsigned int(2) reserved = 0;
* unsigned int(5) NAL_unit_type;
*/
- avio_w8(pb, vvcc->array[i].array_completeness << 7 |
- vvcc->array[i].NAL_unit_type & 0x1f);
+ avio_w8(pb, array->array_completeness << 7 |
+ array->NAL_unit_type & 0x1f);
/* unsigned int(16) num_nalus; */
- if (vvcc->array[i].NAL_unit_type != VVC_DCI_NUT &&
- vvcc->array[i].NAL_unit_type != VVC_OPI_NUT)
- avio_wb16(pb, vvcc->array[i].num_nalus);
- for (j = 0; j < vvcc->array[i].num_nalus; j++) {
+ if (array->NAL_unit_type != VVC_DCI_NUT &&
+ array->NAL_unit_type != VVC_OPI_NUT)
+ avio_wb16(pb, array->num_nalus);
+ for (int j = 0; j < array->num_nalus; j++) {
/* unsigned int(16) nal_unit_length; */
- avio_wb16(pb, vvcc->array[i].nal_unit_length[j]);
+ avio_wb16(pb, array->nal_unit_length[j]);
/* bit(8*nal_unit_length) nal_unit; */
- avio_write(pb, vvcc->array[i].nal_unit[j],
- vvcc->array[i].nal_unit_length[j]);
+ avio_write(pb, array->nal_unit[j],
+ array->nal_unit_length[j]);
}
}
@@ -932,19 +910,18 @@ int ff_isom_write_vvcc(AVIOContext *pb, const uint8_t *data,
buf += 4;
- switch (type) {
- case VVC_OPI_NUT:
- case VVC_VPS_NUT:
- case VVC_SPS_NUT:
- case VVC_PPS_NUT:
- case VVC_PREFIX_SEI_NUT:
- case VVC_SUFFIX_SEI_NUT:
- ret = vvcc_add_nal_unit(buf, len, ps_array_completeness, &vvcc);
- if (ret < 0)
- goto end;
- break;
- default:
- break;
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(vvcc.arrays); i++) {
+ static const uint8_t array_idx_to_type[] =
+ { VVC_OPI_NUT, VVC_VPS_NUT, VVC_SPS_NUT,
+ VVC_PPS_NUT, VVC_PREFIX_SEI_NUT, VVC_SUFFIX_SEI_NUT };
+
+ if (type == array_idx_to_type[i]) {
+ ret = vvcc_add_nal_unit(buf, len, ps_array_completeness,
+ &vvcc, i);
+ if (ret < 0)
+ goto end;
+ break;
+ }
}
buf += len;
--
2.40.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2024-06-05 11:41 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-05 11:37 [FFmpeg-devel] [PATCH 1/7] avcodec/hevc/Makefile: Move rules for lavc/* files to lavc/Makefile Andreas Rheinhardt
2024-06-05 11:40 ` [FFmpeg-devel] [PATCH 2/7] avformat/vvc: Use put_bytes_output() Andreas Rheinhardt
2024-06-05 11:40 ` [FFmpeg-devel] [PATCH 3/7] avformat/vvc: Don't use ff_copy_bits() Andreas Rheinhardt
2024-06-05 11:40 ` Andreas Rheinhardt [this message]
2024-06-05 11:53 ` [FFmpeg-devel] [PATCH 4/7] avformat/vvc: Fix crash on allocation failure, avoid allocations Andreas Rheinhardt
2024-06-06 13:11 ` Nuo Mi
2024-06-06 13:26 ` Nuo Mi
2024-06-08 21:13 ` Andreas Rheinhardt
2024-06-09 0:25 ` Nuo Mi
2024-06-05 11:40 ` [FFmpeg-devel] [PATCH 5/7] avformat/vvc: Reindent after the previous commit Andreas Rheinhardt
2024-06-05 11:40 ` [FFmpeg-devel] [PATCH 6/7] avformat/evc: Fix format specifiers Andreas Rheinhardt
2024-06-05 11:40 ` [FFmpeg-devel] [PATCH 7/7] avcodec/cbs_h266_syntax_template: Use correct format specifier Andreas Rheinhardt
2024-06-08 21:13 ` [FFmpeg-devel] [PATCH 8/9] avformat/vvc: Fix comment Andreas Rheinhardt
2024-06-08 21:13 ` [FFmpeg-devel] [PATCH 9/9] avformat/vvc: Don't use uint8_t iterators, fix shadowing Andreas Rheinhardt
2024-06-08 21:20 ` [FFmpeg-devel] [PATCH 1/7] avcodec/hevc/Makefile: Move rules for lavc/* files to lavc/Makefile Andreas Rheinhardt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=GV1P250MB0737382DBD7B140F7AB307FE8FF92@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM \
--to=andreas.rheinhardt@outlook.com \
--cc=ffmpeg-devel@ffmpeg.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git