Skip to content

Commit 64a48bd

Browse files
ntocmassiot
authored andcommitted
ubuf_av: fix ubuf_sound_resize
Don't modify audio planes content in ubuf_sound_av_resize because the ubuf may not be writable.
1 parent a5c4e65 commit 64a48bd

File tree

3 files changed

+218
-3
lines changed

3 files changed

+218
-3
lines changed

lib/upipe-av/ubuf_av.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,10 +741,20 @@ static int ubuf_sound_av_resize(struct ubuf *ubuf, int offset, int new_size)
741741
else if (offset + new_size > size)
742742
return UBASE_ERR_INVALID;
743743

744-
av_samples_copy(frame->extended_data, frame->extended_data,
745-
0, offset, new_size, frame->ch_layout.nb_channels,
746-
frame->format);
744+
int planar = av_sample_fmt_is_planar(frame->format);
745+
int channels = frame->ch_layout.nb_channels;
746+
int planes = planar ? channels : 1;
747+
748+
for (int i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++)
749+
frame->extended_data[i] = frame->data[i] =
750+
frame->data[i] + offset * sample_size;
751+
752+
for (int i = 0; i < frame->nb_extended_buf; i++)
753+
frame->extended_data[i + AV_NUM_DATA_POINTERS] += offset * sample_size;
754+
747755
frame->nb_samples = new_size;
756+
av_samples_get_buffer_size(&frame->linesize[0], channels,
757+
frame->nb_samples, frame->format, 0);
748758

749759
return UBASE_ERR_NONE;
750760
}

tests/Build.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ distfiles = valgrind_wrapper.sh valgrind.supp \
1919
tests += ubits_test
2020
ubits_test-src = ubits_test.c
2121

22+
tests += ubuf_av_sound_test
23+
ubuf_av_sound_test-src = ubuf_av_sound_test.c
24+
ubuf_av_sound_test-libs = libupipe libupipe_av libavutil
25+
2226
tests += ubuf_block_mem_test
2327
ubuf_block_mem_test-src = ubuf_block_mem_test.c
2428
ubuf_block_mem_test-libs = libupipe

tests/ubuf_av_sound_test.c

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Copyright (C) 2025 EasyTools S.A.S.
3+
*
4+
* Authors: Clément Vasseur
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining
7+
* a copy of this software and associated documentation files (the
8+
* "Software"), to deal in the Software without restriction, including
9+
* without limitation the rights to use, copy, modify, merge, publish,
10+
* distribute, sublicense, and/or sell copies of the Software, and to
11+
* permit persons to whom the Software is furnished to do so, subject
12+
* to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be
15+
* included in all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
/** @file
27+
* @short unit tests for ubuf_av manager for sound formats
28+
*/
29+
30+
#undef NDEBUG
31+
32+
#include "upipe/ubuf_sound.h"
33+
#include "upipe-av/ubuf_av.h"
34+
35+
#include <assert.h>
36+
#include <libavutil/frame.h>
37+
38+
static void fill_in(struct ubuf *ubuf)
39+
{
40+
size_t size;
41+
uint8_t sample_size;
42+
ubase_assert(ubuf_sound_size(ubuf, &size, &sample_size));
43+
int octets = size * sample_size;
44+
45+
const char *channel;
46+
ubuf_sound_foreach_plane(ubuf, channel) {
47+
uint8_t *buffer;
48+
ubase_assert(ubuf_sound_plane_write_uint8_t(ubuf, channel, 0, -1,
49+
&buffer));
50+
51+
for (int x = 0; x < octets; x++)
52+
buffer[x] = (uint8_t)channel[0] + x;
53+
ubase_assert(ubuf_sound_plane_unmap(ubuf, channel, 0, -1));
54+
}
55+
}
56+
57+
int main(int argc, char **argv)
58+
{
59+
struct ubuf_mgr *mgr;
60+
struct ubuf *ubuf1, *ubuf2;
61+
const char *channel;
62+
size_t size;
63+
uint8_t sample_size;
64+
uint8_t *w;
65+
const uint8_t *r;
66+
AVFrame *frame;
67+
68+
/* packed s16 stereo */
69+
mgr = ubuf_av_mgr_alloc();
70+
assert(mgr != NULL);
71+
72+
frame = av_frame_alloc();
73+
assert(frame != NULL);
74+
frame->format = AV_SAMPLE_FMT_S16;
75+
frame->nb_samples = 32;
76+
frame->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
77+
assert(av_frame_get_buffer(frame, 0) == 0);
78+
79+
ubuf1 = ubuf_sound_av_alloc(mgr, frame);
80+
assert(ubuf1 != NULL);
81+
av_frame_unref(frame);
82+
83+
ubase_assert(ubuf_sound_size(ubuf1, &size, &sample_size));
84+
assert(size == 32);
85+
assert(sample_size == 4);
86+
87+
unsigned int nb_planes = 0;
88+
ubuf_sound_foreach_plane(ubuf1, channel) {
89+
nb_planes++;
90+
assert(!strcmp(channel, "lr"));
91+
}
92+
assert(nb_planes == 1);
93+
94+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "lr", 0, -1, &r));
95+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "lr", 0, -1));
96+
97+
fill_in(ubuf1);
98+
99+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "lr", 2, 1, &r));
100+
assert(*r == 'l' + 8);
101+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "lr", 2, 1));
102+
103+
ubuf2 = ubuf_dup(ubuf1);
104+
assert(ubuf2 != NULL);
105+
ubase_nassert(ubuf_sound_plane_write_uint8_t(ubuf1, "lr", 0, -1, &w));
106+
ubuf_free(ubuf2);
107+
108+
ubase_nassert(ubuf_sound_resize(ubuf1, 0, 33));
109+
110+
ubase_assert(ubuf_sound_resize(ubuf1, 2, -1));
111+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "lr", 0, -1, &r));
112+
assert(r[0] == 'l' + 8);
113+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "lr", 0, -1));
114+
115+
ubase_assert(ubuf_sound_resize(ubuf1, 0, 29));
116+
117+
ubuf_free(ubuf1);
118+
119+
ubuf_mgr_release(mgr);
120+
121+
/* planar float 5.1 */
122+
mgr = ubuf_av_mgr_alloc();
123+
assert(mgr != NULL);
124+
125+
frame->format = AV_SAMPLE_FMT_FLTP;
126+
frame->nb_samples = 32;
127+
frame->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1;
128+
assert(av_frame_get_buffer(frame, 0) == 0);
129+
130+
ubuf1 = ubuf_sound_av_alloc(mgr, frame);
131+
assert(ubuf1 != NULL);
132+
av_frame_unref(frame);
133+
134+
ubase_assert(ubuf_sound_size(ubuf1, &size, &sample_size));
135+
assert(size == 32);
136+
assert(sample_size == sizeof(float));
137+
138+
nb_planes = 0;
139+
ubuf_sound_foreach_plane(ubuf1, channel)
140+
nb_planes++;
141+
assert(nb_planes == 6);
142+
143+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "l", 0, -1, &r));
144+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "l", 0, -1));
145+
146+
fill_in(ubuf1);
147+
148+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "l", 2, 1, &r));
149+
assert(*r == 'l' + 8);
150+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "l", 2, 1));
151+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "r", 2, 1, &r));
152+
assert(*r == 'r' + 8);
153+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "r", 2, 1));
154+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "c", 2, 1, &r));
155+
assert(*r == 'c' + 8);
156+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "c", 2, 1));
157+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "L", 2, 1, &r));
158+
assert(*r == 'L' + 8);
159+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "L", 2, 1));
160+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "R", 2, 1, &r));
161+
assert(*r == 'R' + 8);
162+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "R", 2, 1));
163+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "S", 2, 1, &r));
164+
assert(*r == 'S' + 8);
165+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "S", 2, 1));
166+
167+
ubuf2 = ubuf_dup(ubuf1);
168+
assert(ubuf2 != NULL);
169+
ubase_nassert(ubuf_sound_plane_write_uint8_t(ubuf1, "l", 0, -1, &w));
170+
ubuf_free(ubuf2);
171+
172+
ubase_nassert(ubuf_sound_resize(ubuf1, 0, 33));
173+
174+
ubase_assert(ubuf_sound_resize(ubuf1, 2, -1));
175+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "l", 0, -1, &r));
176+
assert(r[0] == 'l' + 8);
177+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "l", 0, -1));
178+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "r", 0, -1, &r));
179+
assert(r[0] == 'r' + 8);
180+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "r", 0, -1));
181+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "c", 0, -1, &r));
182+
assert(r[0] == 'c' + 8);
183+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "c", 0, -1));
184+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "L", 0, -1, &r));
185+
assert(r[0] == 'L' + 8);
186+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "L", 0, -1));
187+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "R", 0, -1, &r));
188+
assert(r[0] == 'R' + 8);
189+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "R", 0, -1));
190+
ubase_assert(ubuf_sound_plane_read_uint8_t(ubuf1, "S", 0, -1, &r));
191+
assert(r[0] == 'S' + 8);
192+
ubase_assert(ubuf_sound_plane_unmap(ubuf1, "S", 0, -1));
193+
194+
ubase_assert(ubuf_sound_resize(ubuf1, 0, 29));
195+
196+
ubuf_free(ubuf1);
197+
ubuf_mgr_release(mgr);
198+
av_frame_free(&frame);
199+
200+
return 0;
201+
}

0 commit comments

Comments
 (0)