Check VPS HRD and log actual codec constraints on rejection
This commit is contained in:
1 parent
005d891fb4
commit
047927a7a5
2 files changed
+22
-5
No files matched your search
@@ -60,7 +60,8 @@ static int fits(const struct call_video_limit *l, const struct call_video_format
|
||||
}
|
||||
int call_video_choose(const struct call_video_caps *sender, const struct call_video_caps *receiver,
|
||||
struct call_video_format *format) {
|
||||
if (!call_video_caps_valid(sender) || !call_video_caps_valid(receiver) || !format || format->codec > 2 || format->level) {
|
||||
if (!call_video_caps_valid(sender) || !call_video_caps_valid(receiver) || !format || format->codec > 2
|
||||
|| format->level || format->profile > 2 || (format->codec == CALL_VIDEO_H265 && format->profile > 1)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video choose invalid capabilities/request"); return -1;
|
||||
}
|
||||
struct call_video_format f = *format;
|
||||
|
||||
@@ -95,7 +95,10 @@ static int hevc_ptl(struct bits *b, struct call_video_bitstream *s) {
|
||||
get(b, 32); // profile compatibility; принимаем только явный Main.
|
||||
get(b, 1); unsigned interlaced = get(b, 1); get(b, 2);
|
||||
get(b, 32); get(b, 12); s->level = get(b, 8); s->profile = CALL_VIDEO_MAIN;
|
||||
if (space || tier || profile != 1 || interlaced) return bad("HEVC profile/tier/interlace");
|
||||
if (space || tier || profile != 1 || interlaced) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CALL, "video HEVC PTL rejected space=%u profile=%u tier=%u level=%u interlaced=%u",
|
||||
space, profile, tier, s->level, interlaced); return -1;
|
||||
}
|
||||
return b->error ? bad("truncated HEVC PTL") : 0;
|
||||
}
|
||||
/* HEVC HRD для единственного temporal layer; sub-picture HRD звонкам не требуется. */
|
||||
@@ -219,13 +222,24 @@ int call_video_inspect_key(int codec, const uint8_t *data, size_t length, struct
|
||||
if (have_sps && (memcmp(&parsed, &stream, sizeof(parsed)) || id != sps_id)) { bad("multiple AVC SPS"); goto done; }
|
||||
stream = parsed; sps_id = id; have_sps = 1;
|
||||
} else if (codec == 2 && type == 32) {
|
||||
struct call_video_bitstream parsed = {0};
|
||||
unsigned id = get(&b, 4); get(&b, 2);
|
||||
if (get(&b, 6) || get(&b, 3) || !get(&b, 1) || get(&b, 16) != 65535 || hevc_ptl(&b, &vp)) {
|
||||
if (get(&b, 6) || get(&b, 3) || !get(&b, 1) || get(&b, 16) != 65535 || hevc_ptl(&b, &parsed)) {
|
||||
bad("HEVC VPS layers/PTL"); goto done;
|
||||
}
|
||||
get(&b, 1); unsigned dpb = ue(&b) + 1, reorder = ue(&b); ue(&b);
|
||||
if (b.error || reorder || dpb > 16 || (have_vps && id != vps_id)) { bad("HEVC VPS DPB"); goto done; }
|
||||
vp.dpb = dpb; vps_id = id; have_vps = 1;
|
||||
if (b.error || reorder || dpb > 16) { bad("HEVC VPS DPB"); goto done; }
|
||||
parsed.dpb = dpb;
|
||||
if (have_vps && (id != vps_id || memcmp(&parsed, &vp, sizeof(vp)))) { bad("multiple HEVC VPS"); goto done; }
|
||||
if (get(&b, 6) || ue(&b)) { bad("HEVC VPS layer sets"); goto done; }
|
||||
if (get(&b, 1)) {
|
||||
get(&b, 32); get(&b, 32); if (get(&b, 1)) ue(&b);
|
||||
unsigned count = ue(&b);
|
||||
if (count > 1) { bad("HEVC VPS HRD count"); goto done; }
|
||||
if (count) { if (ue(&b)) { bad("HEVC VPS HRD layer"); goto done; } hevc_hrd(&b, parsed.level); }
|
||||
}
|
||||
if (get(&b, 1) || b.error) { bad("HEVC VPS extension/truncation/HRD"); goto done; }
|
||||
vp = parsed; vps_id = id; have_vps = 1;
|
||||
} else if (codec == 2 && type == 33) {
|
||||
struct call_video_bitstream parsed = {0}; unsigned id, vps;
|
||||
if (hevc_sps(&b, &parsed, &id, &vps)) goto done;
|
||||
@@ -271,6 +285,8 @@ int call_video_inspect_key(int codec, const uint8_t *data, size_t length, struct
|
||||
|| vp.profile != stream.profile || vp.level != stream.level || stream.dpb > vp.dpb))) {
|
||||
bad("missing/inconsistent parameter sets or IDR"); goto done;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "video bitstream verified codec=%d profile=%u level=%u size=%ux%u dpb=%u slices=%u",
|
||||
codec, stream.profile, stream.level, stream.width, stream.height, stream.dpb, slices);
|
||||
*out = stream; result = 0;
|
||||
done:
|
||||
u_free(scratch); return result;
|
||||
|
||||
Reference in new issue
Block a user