From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
To: ffmpeg-devel@ffmpeg.org
Subject: Re: [FFmpeg-devel] [PATCH] avocdec/hevc_ps: don't use a fixed sized buffer for parameter set raw data
Date: Fri, 29 Mar 2024 17:31:12 +0100
Message-ID: <AS8P250MB0744A427E17653607475762D8F3A2@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <88b558f7-df39-4078-b256-ab94a5e20d7f@gmail.com>
James Almer:
> On 3/29/2024 1:10 PM, Andreas Rheinhardt wrote:
>> James Almer:
>>> Allocate it instead, and use it to compare sets instead of the parsed
>>> struct.
>>>
>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>> ---
>>> libavcodec/hevc_ps.c | 84 ++++++++++++++++++++++----------------------
>>> libavcodec/hevc_ps.h | 14 +++++---
>>> 2 files changed, 51 insertions(+), 47 deletions(-)
>>>
>>> diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c
>>> index 6475d86d7d..e417039d76 100644
>>> --- a/libavcodec/hevc_ps.c
>>> +++ b/libavcodec/hevc_ps.c
>>> @@ -442,20 +442,18 @@ static int decode_hrd(GetBitContext *gb, int
>>> common_inf_present,
>>> return 0;
>>> }
>>> -static void uninit_vps(FFRefStructOpaque opaque, void *obj)
>>> +static void hevc_vps_free(FFRefStructOpaque opaque, void *obj)
>>> {
>>> HEVCVPS *vps = obj;
>>> av_freep(&vps->hdr);
>>> + av_freep(&vps->data);
>>> }
>>> static int compare_vps(const HEVCVPS *vps1, const HEVCVPS *vps2)
>>> {
>>> - if (!memcmp(vps1, vps2, offsetof(HEVCVPS, hdr)))
>>> - return !vps1->vps_num_hrd_parameters ||
>>> - !memcmp(vps1->hdr, vps2->hdr,
>>> vps1->vps_num_hrd_parameters * sizeof(*vps1->hdr));
>>> -
>>> - return 0;
>>> + return vps1->data_size == vps2->data_size &&
>>> + !memcmp(vps1->data, vps2->data, vps1->data_size);
>>> }
>>> int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx,
>>> @@ -463,25 +461,20 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb,
>>> AVCodecContext *avctx,
>>> {
>>> int i,j;
>>> int vps_id = 0;
>>> - ptrdiff_t nal_size;
>>> - HEVCVPS *vps = ff_refstruct_alloc_ext(sizeof(*vps), 0, NULL,
>>> uninit_vps);
>>> + int ret = AVERROR_INVALIDDATA;
>>> + HEVCVPS *vps = ff_refstruct_alloc_ext(sizeof(*vps), 0, NULL,
>>> hevc_vps_free);
>>> if (!vps)
>>> return AVERROR(ENOMEM);
>>> av_log(avctx, AV_LOG_DEBUG, "Decoding VPS\n");
>>> - nal_size = gb->buffer_end - gb->buffer;
>>> - if (nal_size > sizeof(vps->data)) {
>>> - av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized
>>> VPS "
>>> - "(%"PTRDIFF_SPECIFIER" > %"SIZE_SPECIFIER")\n",
>>> - nal_size, sizeof(vps->data));
>>> - vps->data_size = sizeof(vps->data);
>>> - } else {
>>> - vps->data_size = nal_size;
>>> + vps->data_size = gb->buffer_end - gb->buffer;
>>> + vps->data = av_memdup(gb->buffer, vps->data_size);
>>> + if (!vps->data) {
>>> + ret = AVERROR(ENOMEM);
>>> + goto err;
>>> }
>>> - memcpy(vps->data, gb->buffer, vps->data_size);
>>> -
>>> vps_id = vps->vps_id = get_bits(gb, 4);
>>> if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits
>>> @@ -591,7 +584,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb,
>>> AVCodecContext *avctx,
>>> err:
>>> ff_refstruct_unref(&vps);
>>> - return AVERROR_INVALIDDATA;
>>> + return ret;
>>> }
>>> static void decode_vui(GetBitContext *gb, AVCodecContext *avctx,
>>> @@ -1294,36 +1287,43 @@ int ff_hevc_parse_sps(HEVCSPS *sps,
>>> GetBitContext *gb, unsigned int *sps_id,
>>> return 0;
>>> }
>>> +static void hevc_sps_free(FFRefStructOpaque opaque, void *obj)
>>> +{
>>> + HEVCSPS *sps = obj;
>>> +
>>> + av_freep(&sps->data);
>>> +}
>>> +
>>> +static int compare_sps(const HEVCSPS *sps1, const HEVCSPS *sps2)
>>> +{
>>> + return sps1->data_size == sps2->data_size &&
>>> + !memcmp(sps1->data, sps2->data, sps1->data_size);
>>> +}
>>> +
>>> int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx,
>>> HEVCParamSets *ps, int apply_defdispwin)
>>> {
>>> - HEVCSPS *sps = ff_refstruct_allocz(sizeof(*sps));
>>> + HEVCSPS *sps = ff_refstruct_alloc_ext(sizeof(*sps), 0, NULL,
>>> hevc_sps_free);
>>> unsigned int sps_id;
>>> int ret;
>>> - ptrdiff_t nal_size;
>>> if (!sps)
>>> return AVERROR(ENOMEM);
>>> av_log(avctx, AV_LOG_DEBUG, "Decoding SPS\n");
>>> - nal_size = gb->buffer_end - gb->buffer;
>>> - if (nal_size > sizeof(sps->data)) {
>>> - av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized
>>> SPS "
>>> - "(%"PTRDIFF_SPECIFIER" > %"SIZE_SPECIFIER")\n",
>>> - nal_size, sizeof(sps->data));
>>> - sps->data_size = sizeof(sps->data);
>>> - } else {
>>> - sps->data_size = nal_size;
>>> + sps->data_size = gb->buffer_end - gb->buffer;
>>> + sps->data = av_memdup(gb->buffer, sps->data_size);
>>> + if (!sps->data) {
>>> + ret = AVERROR(ENOMEM);
>>> + goto err;
>>> }
>>> - memcpy(sps->data, gb->buffer, sps->data_size);
>>> ret = ff_hevc_parse_sps(sps, gb, &sps_id,
>>> apply_defdispwin,
>>> ps->vps_list, avctx);
>>> if (ret < 0) {
>>> - ff_refstruct_unref(&sps);
>>> - return ret;
>>> + goto err;
>>> }
>>> if (avctx->debug & FF_DEBUG_BITSTREAM) {
>>> @@ -1340,7 +1340,7 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb,
>>> AVCodecContext *avctx,
>>> * original one.
>>> * otherwise drop all PPSes that depend on it */
>>> if (ps->sps_list[sps_id] &&
>>> - !memcmp(ps->sps_list[sps_id], sps, sizeof(*sps))) {
>>> + compare_sps(ps->sps_list[sps_id], sps)) {
>>> ff_refstruct_unref(&sps);
>>> } else {
>>> remove_sps(ps, sps_id);
>>> @@ -1348,6 +1348,9 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb,
>>> AVCodecContext *avctx,
>>> }
>>> return 0;
>>> +err:
>>> + ff_refstruct_unref(&sps);
>>> + return ret;
>>> }
>>> static void hevc_pps_free(FFRefStructOpaque unused, void *obj)
>>> @@ -1364,6 +1367,7 @@ static void hevc_pps_free(FFRefStructOpaque
>>> unused, void *obj)
>>> av_freep(&pps->tile_pos_rs);
>>> av_freep(&pps->tile_id);
>>> av_freep(&pps->min_tb_addr_zs_tab);
>>> + av_freep(&pps->data);
>>> }
>>> static void colour_mapping_octants(GetBitContext *gb, HEVCPPS
>>> *pps, int inp_depth,
>>> @@ -1773,16 +1777,12 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb,
>>> AVCodecContext *avctx,
>>> av_log(avctx, AV_LOG_DEBUG, "Decoding PPS\n");
>>> - nal_size = gb->buffer_end - gb->buffer;
>>> - if (nal_size > sizeof(pps->data)) {
>>> - av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized
>>> PPS "
>>> - "(%"PTRDIFF_SPECIFIER" > %"SIZE_SPECIFIER")\n",
>>> - nal_size, sizeof(pps->data));
>>> - pps->data_size = sizeof(pps->data);
>>> - } else {
>>> - pps->data_size = nal_size;
>>> + pps->data_size = gb->buffer_end - gb->buffer;
>>> + pps->data = av_memdup(gb->buffer, pps->data_size);
>>> + if (!pps->data) {
>>> + ret = AVERROR_INVALIDDATA;
>>> + goto err;
>>> }
>>> - memcpy(pps->data, gb->buffer, pps->data_size);
>>> // Default values
>>> pps->loop_filter_across_tiles_enabled_flag = 1;
>>> diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h
>>> index 0d8eaf2b3e..bed406770f 100644
>>> --- a/libavcodec/hevc_ps.h
>>> +++ b/libavcodec/hevc_ps.h
>>> @@ -172,11 +172,11 @@ typedef struct HEVCVPS {
>>> int vps_num_ticks_poc_diff_one; ///<
>>> vps_num_ticks_poc_diff_one_minus1 + 1
>>> int vps_num_hrd_parameters;
>>> - uint8_t data[4096];
>>> - int data_size;
>>> - /* Put this at the end of the structure to make it easier to
>>> calculate the
>>> + /* Keep this at the end of the structure to make it easier to
>>> calculate the
>>> * size before this pointer, which is used for memcmp */
>>> HEVCHdrParams *hdr;
>>> + uint8_t *data;
>>> + int data_size;
>>> } HEVCVPS;
>>> typedef struct ScalingList {
>>> @@ -299,7 +299,9 @@ typedef struct HEVCSPS {
>>> int qp_bd_offset;
>>> - uint8_t data[4096];
>>> + /* Keep this at the end of the structure to make it easier to
>>> calculate the
>>> + * size before this pointer, which is used for memcmp */
>>> + uint8_t *data;
>>> int data_size;
>>> } HEVCSPS;
>>> @@ -434,7 +436,9 @@ typedef struct HEVCPPS {
>>> int *min_tb_addr_zs; ///< MinTbAddrZS
>>> int *min_tb_addr_zs_tab;///< MinTbAddrZS
>>> - uint8_t data[4096];
>>> + /* Keep this at the end of the structure to make it easier to
>>> calculate the
>>> + * size before this pointer, which is used for memcmp */
>>> + uint8_t *data;
>>> int data_size;
>>> } HEVCPPS;
>>>
>>
>> This is vastly overcomplicated: If you already have the complete data of
>> the earlier PS, all you need is comparing the data before you even parse
>> the new parameter set.
>
> Need to get sps_id from the new sps buffer, which requires calling
> ff_hevc_parse_sps(). Same for pps to get pps_id. Only vps has its id as
> the very first element.
No. SPS is the only exception.
- Andreas
_______________________________________________
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-03-29 16:31 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-29 15:56 James Almer
2024-03-29 16:10 ` Andreas Rheinhardt
2024-03-29 16:17 ` James Almer
2024-03-29 16:31 ` Andreas Rheinhardt [this message]
2024-03-29 16:59 ` [FFmpeg-devel] [PATCH v2] " James Almer
2024-03-29 17:28 ` Andreas Rheinhardt
2024-03-29 17:36 ` James Almer
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=AS8P250MB0744A427E17653607475762D8F3A2@AS8P250MB0744.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