Skip to content

Commit e59fa34

Browse files
committed
fix: address parameter set parsing review
1 parent 8651252 commit e59fa34

4 files changed

Lines changed: 168 additions & 51 deletions

File tree

libflv/source/hevc-annexbtomp4.c

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct h265_annexbtomp4_handle_t
2929
size_t capacity;
3030
};
3131

32-
int mpeg4_h264_read_ue(const uint8_t* data, size_t bytes, size_t* offset, uint8_t* value);
32+
int mpeg4_h264_read_ue(const uint8_t* data, size_t bytes, size_t* offset, uint32_t* value);
3333

3434
static size_t hevc_rbsp_decode(const uint8_t* nalu, size_t bytes, uint8_t* sodb, size_t len)
3535
{
@@ -127,13 +127,17 @@ static uint8_t hevc_vps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_
127127

128128
static uint8_t hevc_sps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_t* hevc, uint8_t* ptr, size_t len, uint8_t* vps)
129129
{
130+
int ptl_bytes;
130131
size_t n;
131132
size_t sodb;
132-
uint8_t sps;
133+
uint32_t sps;
134+
uint32_t chroma_format;
135+
uint32_t bit_depth_luma_minus8;
136+
uint32_t bit_depth_chroma_minus8;
133137
uint8_t sps_max_sub_layers_minus1;
134138
uint8_t sps_temporal_id_nesting_flag;
135139
uint8_t conformance_window_flag;
136-
uint8_t value;
140+
uint32_t value;
137141

138142
sodb = hevc_rbsp_decode(rbsp, bytes, ptr, len);
139143
if (sodb < 12+3)
@@ -142,15 +146,17 @@ static uint8_t hevc_sps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_
142146
*vps = ptr[2] >> 4; // 2-nalu type
143147
sps_max_sub_layers_minus1 = (ptr[2] >> 1) & 0x07;
144148
sps_temporal_id_nesting_flag = ptr[2] & 0x01;
145-
n = hevc_profile_tier_level(ptr + 3, sodb - 3, sps_max_sub_layers_minus1, hevc);
146-
if (n <= 0)
149+
ptl_bytes = hevc_profile_tier_level(ptr + 3, sodb - 3, sps_max_sub_layers_minus1, hevc);
150+
if (ptl_bytes <= 0)
147151
return 0xFF;
148152

149-
n = (n + 3) * 8;
153+
n = ((size_t)ptl_bytes + 3) * 8;
150154
if (mpeg4_h264_read_ue(ptr, sodb, &n, &sps) < 0
151-
|| mpeg4_h264_read_ue(ptr, sodb, &n, &hevc->chromaFormat) < 0)
155+
|| mpeg4_h264_read_ue(ptr, sodb, &n, &chroma_format) < 0
156+
|| sps >= 16 || chroma_format > 3)
152157
return 0xFF;
153-
if (3 == hevc->chromaFormat)
158+
hevc->chromaFormat = (uint8_t)chroma_format;
159+
if (3 == chroma_format)
154160
{
155161
if (n / 8 >= sodb)
156162
return 0xFF;
@@ -170,28 +176,47 @@ static uint8_t hevc_sps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_
170176
|| mpeg4_h264_read_ue(ptr, sodb, &n, &value) < 0) // conf_win_bottom_offset
171177
return 0xFF;
172178
}
173-
if (mpeg4_h264_read_ue(ptr, sodb, &n, &hevc->bitDepthLumaMinus8) < 0
174-
|| mpeg4_h264_read_ue(ptr, sodb, &n, &hevc->bitDepthChromaMinus8) < 0)
179+
if (mpeg4_h264_read_ue(ptr, sodb, &n, &bit_depth_luma_minus8) < 0
180+
|| mpeg4_h264_read_ue(ptr, sodb, &n, &bit_depth_chroma_minus8) < 0
181+
|| bit_depth_luma_minus8 > 7 || bit_depth_chroma_minus8 > 7)
175182
return 0xFF;
183+
hevc->bitDepthLumaMinus8 = (uint8_t)bit_depth_luma_minus8;
184+
hevc->bitDepthChromaMinus8 = (uint8_t)bit_depth_chroma_minus8;
176185

177186
// TODO: vui_parameters
178187
//mp4->hevc->min_spatial_segmentation_idc; // min_spatial_segmentation_idc
179-
return sps;
188+
return (uint8_t)sps;
189+
}
190+
191+
static void hevc_sps_apply(struct mpeg4_hevc_t* hevc, const struct mpeg4_hevc_t* parsed)
192+
{
193+
hevc->general_profile_space = parsed->general_profile_space;
194+
hevc->general_tier_flag = parsed->general_tier_flag;
195+
hevc->general_profile_idc = parsed->general_profile_idc;
196+
hevc->general_profile_compatibility_flags = parsed->general_profile_compatibility_flags;
197+
hevc->general_constraint_indicator_flags = parsed->general_constraint_indicator_flags;
198+
hevc->general_level_idc = parsed->general_level_idc;
199+
hevc->chromaFormat = parsed->chromaFormat;
200+
hevc->bitDepthLumaMinus8 = parsed->bitDepthLumaMinus8;
201+
hevc->bitDepthChromaMinus8 = parsed->bitDepthChromaMinus8;
180202
}
181203

182204
static uint8_t hevc_pps_id(const uint8_t* rbsp, size_t bytes, struct mpeg4_hevc_t* hevc, uint8_t* ptr, size_t len, uint8_t* sps)
183205
{
184-
uint8_t pps;
206+
uint32_t pps;
207+
uint32_t spsid;
185208
size_t sodb;
186209
size_t offset = 2 * 8; // 2-nalu type
187210
sodb = hevc_rbsp_decode(rbsp, bytes, ptr, len);
188211
if (sodb < 3)
189212
return 0xFF;
190213
(void)hevc;
191214
if (mpeg4_h264_read_ue(ptr, sodb, &offset, &pps) < 0
192-
|| mpeg4_h264_read_ue(ptr, sodb, &offset, sps) < 0)
215+
|| mpeg4_h264_read_ue(ptr, sodb, &offset, &spsid) < 0
216+
|| pps >= 64 || spsid >= 16)
193217
return 0xFF;
194-
return pps;
218+
*sps = (uint8_t)spsid;
219+
return (uint8_t)pps;
195220
}
196221

197222
static void mpeg4_hevc_remove(struct mpeg4_hevc_t* hevc, uint8_t* ptr, size_t bytes, const uint8_t* end)
@@ -273,25 +298,40 @@ static int h265_vps_copy(struct mpeg4_hevc_t* hevc, const uint8_t* nalu, size_t
273298
static int h265_sps_copy(struct mpeg4_hevc_t* hevc, const uint8_t* nalu, size_t bytes)
274299
{
275300
int i;
301+
int r;
276302
uint8_t spsid;
303+
uint8_t spsid2;
277304
uint8_t vpsid, vpsid2;
305+
struct mpeg4_hevc_t parsed;
306+
struct mpeg4_hevc_t parsed2;
278307

279308
if (bytes < 13 + 2)
280309
{
281310
assert(0);
282311
return -1; // invalid length
283312
}
284313

285-
spsid = hevc_sps_id(nalu, bytes, hevc, hevc->data + hevc->off, sizeof(hevc->data) - hevc->off, &vpsid);
314+
spsid = hevc_sps_id(nalu, bytes, &parsed, hevc->data + hevc->off, sizeof(hevc->data) - hevc->off, &vpsid);
286315
if (0xFF == spsid)
287316
return -1;
288317
for (i = 0; i < hevc->numOfArrays; i++)
289318
{
290-
if (H265_NAL_SPS == hevc->nalu[i].type && spsid == hevc_sps_id(hevc->nalu[i].data, hevc->nalu[i].bytes, hevc, hevc->data + hevc->off, sizeof(hevc->data) - hevc->off, &vpsid2) && vpsid == vpsid2)
291-
return mpeg4_hevc_update2(hevc, i, nalu, bytes);
319+
if (H265_NAL_SPS != hevc->nalu[i].type)
320+
continue;
321+
spsid2 = hevc_sps_id(hevc->nalu[i].data, hevc->nalu[i].bytes, &parsed2, hevc->data + hevc->off, sizeof(hevc->data) - hevc->off, &vpsid2);
322+
if (spsid == spsid2 && vpsid == vpsid2)
323+
{
324+
r = mpeg4_hevc_update2(hevc, i, nalu, bytes);
325+
if (r >= 0)
326+
hevc_sps_apply(hevc, &parsed);
327+
return r;
328+
}
292329
}
293330

294-
return mpeg4_hevc_add(hevc, H265_NAL_SPS, nalu, bytes);
331+
r = mpeg4_hevc_add(hevc, H265_NAL_SPS, nalu, bytes);
332+
if (r >= 0)
333+
hevc_sps_apply(hevc, &parsed);
334+
return r;
295335
}
296336

297337
static int h265_pps_copy(struct mpeg4_hevc_t* hevc, const uint8_t* nalu, size_t bytes)
@@ -476,12 +516,15 @@ void hevc_annexbtomp4_test(void)
476516
const uint8_t vps[] = { 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0x9d, 0xc0, 0x90 };
477517
const uint8_t sps[] = { 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x32, 0x16, 0x59, 0xde, 0x49, 0x1b, 0x6b, 0x80, 0x40, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x17, 0x70, 0x02 };
478518
const uint8_t pps[] = { 0x44, 0x01, 0xc1, 0x73, 0xd1, 0x89 };
519+
const uint8_t truncated_ptl_sps[] = { 0x42, 0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
520+
const uint8_t truncated_sps[] = { 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78 };
479521
const uint8_t incomplete_pps[] = { 0x44, 0x01, 0x01 };
480522
const uint8_t annexb[] = { 0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x06, 0x01, 0xd0, 0x80, 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0x9d, 0xc0, 0x90, 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x32, 0x16, 0x59, 0xde, 0x49, 0x1b, 0x6b, 0x80, 0x40, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x17, 0x70, 0x02, 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x73, 0xd1, 0x89 };
481523
uint8_t output[512];
482524
int vcl, update;
483525

484526
struct mpeg4_hevc_t hevc;
527+
struct mpeg4_hevc_t before;
485528
memset(&hevc, 0, sizeof(hevc));
486529
assert(h265_annexbtomp4(&hevc, annexb, sizeof(annexb), output, sizeof(output), &vcl, &update) > 0);
487530
assert(3 == hevc.numOfArrays && vcl == 0 && update == 1);
@@ -492,5 +535,21 @@ void hevc_annexbtomp4_test(void)
492535
memset(&hevc, 0, sizeof(hevc));
493536
assert(mpeg4_hevc_update(&hevc, incomplete_pps, sizeof(incomplete_pps)) < 0);
494537
assert(0 == hevc.numOfArrays && 0 == hevc.off);
538+
539+
memset(&hevc, 0x5a, offsetof(struct mpeg4_hevc_t, numOfArrays));
540+
hevc.numOfArrays = 0;
541+
hevc.off = 0;
542+
before = hevc;
543+
assert(mpeg4_hevc_update(&hevc, truncated_ptl_sps, sizeof(truncated_ptl_sps)) < 0);
544+
assert(0 == memcmp(&before, &hevc, offsetof(struct mpeg4_hevc_t, numOfArrays)));
545+
assert(0 == hevc.numOfArrays && 0 == hevc.off);
546+
547+
memset(&hevc, 0x5a, offsetof(struct mpeg4_hevc_t, numOfArrays));
548+
hevc.numOfArrays = 0;
549+
hevc.off = 0;
550+
before = hevc;
551+
assert(mpeg4_hevc_update(&hevc, truncated_sps, sizeof(truncated_sps)) < 0);
552+
assert(0 == memcmp(&before, &hevc, offsetof(struct mpeg4_hevc_t, numOfArrays)));
553+
assert(0 == hevc.numOfArrays && 0 == hevc.off);
495554
}
496555
#endif

libflv/source/mpeg4-annexbtomp4.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ int mpeg4_h264_annexb_nalu(const void* h264, size_t bytes, void (*handler)(void*
161161
return 0;
162162
}
163163

164-
int mpeg4_h264_read_ue(const uint8_t* data, size_t bytes, size_t* offset, uint8_t* value)
164+
int mpeg4_h264_read_ue(const uint8_t* data, size_t bytes, size_t* offset, uint32_t* value)
165165
{
166166
int bit, i;
167167
int leadingZeroBits = 0;
@@ -188,7 +188,7 @@ int mpeg4_h264_read_ue(const uint8_t* data, size_t bytes, size_t* offset, uint8_
188188
++*offset;
189189
}
190190

191-
*value = (uint8_t)((1U << leadingZeroBits) - 1 + suffix);
191+
*value = (1U << leadingZeroBits) - 1 + suffix;
192192
return 0;
193193
}
194194

@@ -215,8 +215,8 @@ static int h264_sps_copy(struct mpeg4_avc_t* avc, const uint8_t* nalu, size_t by
215215
{
216216
size_t i;
217217
size_t offset;
218-
uint8_t spsid;
219-
uint8_t spsid2;
218+
uint32_t spsid;
219+
uint32_t spsid2;
220220

221221
if (bytes < 4 + 1)
222222
{
@@ -225,7 +225,7 @@ static int h264_sps_copy(struct mpeg4_avc_t* avc, const uint8_t* nalu, size_t by
225225
}
226226

227227
offset = 4 * 8; // 1-NALU + 3-profile+flags+level
228-
if (mpeg4_h264_read_ue(nalu, bytes, &offset, &spsid) < 0)
228+
if (mpeg4_h264_read_ue(nalu, bytes, &offset, &spsid) < 0 || spsid >= 32)
229229
return -1;
230230

231231
for (i = 0; i < avc->nb_sps; i++)
@@ -276,10 +276,10 @@ static int h264_pps_copy(struct mpeg4_avc_t* avc, const uint8_t* nalu, size_t by
276276
{
277277
size_t i;
278278
size_t offset;
279-
uint8_t spsid;
280-
uint8_t spsid2;
281-
uint8_t ppsid;
282-
uint8_t ppsid2;
279+
uint32_t spsid;
280+
uint32_t spsid2;
281+
uint32_t ppsid;
282+
uint32_t ppsid2;
283283

284284
if (bytes < 1 + 1)
285285
{
@@ -289,7 +289,8 @@ static int h264_pps_copy(struct mpeg4_avc_t* avc, const uint8_t* nalu, size_t by
289289

290290
offset = 1 * 8; // 1-NALU
291291
if (mpeg4_h264_read_ue(nalu, bytes, &offset, &ppsid) < 0
292-
|| mpeg4_h264_read_ue(nalu, bytes, &offset, &spsid) < 0)
292+
|| mpeg4_h264_read_ue(nalu, bytes, &offset, &spsid) < 0
293+
|| ppsid >= 256 || spsid >= 32)
293294
return -1;
294295

295296
for (i = 0; i < avc->nb_pps; i++)
@@ -359,7 +360,7 @@ int mpeg4_avc_update(struct mpeg4_avc_t* avc, const uint8_t* nalu, size_t bytes)
359360
{
360361
case H264_NAL_SPS:
361362
r = h264_sps_copy(avc, nalu, bytes);
362-
if (1 == r || 1 == avc->nb_sps)
363+
if (r >= 0 && (1 == r || 1 == avc->nb_sps))
363364
{
364365
// update profile/level
365366
avc->profile = nalu[1];
@@ -520,9 +521,13 @@ void mpeg4_annexbtomp4_test(void)
520521
{
521522
const uint8_t sps[] = { 0x67,0x42,0xe0,0x1e,0xab };
522523
const uint8_t pps[] = { 0x28,0xce,0x3c,0x80 };
524+
const uint8_t oversized_sps_id[] = { 0x67,0x64,0x00,0x28,0x00,0x80,0x80 };
525+
const uint8_t truncated_sps[] = { 0x67,0x64,0x00,0x28,0x00 };
523526
const uint8_t truncated_pps[] = { 0x68,0x01 };
524527
const uint8_t annexb[] = { 0x00,0x00,0x00,0x01,0x67,0x42,0xe0,0x1e,0xab, 0x00,0x00,0x00,0x01,0x28,0xce,0x3c,0x80,0x00,0x00,0x00,0x01,0x65,0x11 };
525528
uint8_t output[256];
529+
uint8_t profile, compatibility, level;
530+
size_t off;
526531
int vcl, update;
527532

528533
struct mpeg4_avc_t avc;
@@ -536,6 +541,20 @@ void mpeg4_annexbtomp4_test(void)
536541
assert(mpeg4_avc_update(&avc, truncated_pps, sizeof(truncated_pps)) < 0);
537542
assert(0 == avc.nb_pps && 0 == avc.off);
538543

544+
memset(&avc, 0, sizeof(avc));
545+
assert(mpeg4_avc_update(&avc, oversized_sps_id, sizeof(oversized_sps_id)) < 0);
546+
assert(0 == avc.nb_sps && 0 == avc.off);
547+
548+
memset(&avc, 0, sizeof(avc));
549+
assert(mpeg4_avc_update(&avc, sps, sizeof(sps)) > 0);
550+
profile = avc.profile;
551+
compatibility = avc.compatibility;
552+
level = avc.level;
553+
off = avc.off;
554+
assert(mpeg4_avc_update(&avc, truncated_sps, sizeof(truncated_sps)) < 0);
555+
assert(profile == avc.profile && compatibility == avc.compatibility && level == avc.level);
556+
assert(1 == avc.nb_sps && off == avc.off && 0 == memcmp(avc.sps[0].data, sps, sizeof(sps)));
557+
539558
mpeg4_annexbtomp4_test2();
540559
mpeg4_h264_bitstream_format_test();
541560
}

libflv/source/mpeg4-vvc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,5 +426,6 @@ void mpeg4_vvc_test(void)
426426
assert(2 == vvc.numOfArrays && H266_SPS == vvc.nalu[0].type && 0x2a == vvc.nalu[0].bytes && H266_PPS == vvc.nalu[1].type && 0x0c == vvc.nalu[1].bytes);
427427
assert(sizeof(data) == mpeg4_vvc_decoder_configuration_record_save(&vvc, buffer, sizeof(buffer)) && 0 == memcmp(buffer, data, sizeof(data)));
428428
mpeg4_vvc_codecs_test(&vvc);
429+
vvc_annexbtomp4_test();
429430
}
430431
#endif

0 commit comments

Comments
 (0)