diff --git a/media/parsers/h265_parser.cc b/media/parsers/h265_parser.cc index 2b41700f0f51e..60674efb838ae 100644 --- a/media/parsers/h265_parser.cc +++ b/media/parsers/h265_parser.cc @@ -883,6 +883,28 @@ H265Parser::Result H265Parser::ParseSPS(int* sps_id) { // If an SPS with the same id already exists, replace it. *sps_id = sps->sps_seq_parameter_set_id; + // ParsePPS() validates several PPS fields (num_tile_columns_minus1, + // num_tile_rows_minus1, diff_cu_qp_delta_depth, diff_cu_chroma_qp_offset_depth, + // log2_parallel_merge_level_minus2, init_qp_minus26) against whichever SPS is + // present at PPS-parse time. If a new SPS with the same id changes any of the + // bounds those checks depend on, the previously-validated PPSes are no longer + // known-good and must not be shipped to the platform accelerator alongside the + // new SPS. Drop them so the stream is forced to re-send (and re-validate) a + // PPS. This mirrors FFmpeg's remove_sps() (libavcodec/hevc/ps.c). + auto old = active_sps_.find(*sps_id); + if (old != active_sps_.end()) { + const H265SPS& o = *old->second; + if (o.pic_width_in_ctbs_y != sps->pic_width_in_ctbs_y || + o.pic_height_in_ctbs_y != sps->pic_height_in_ctbs_y || + o.ctb_log2_size_y != sps->ctb_log2_size_y || + o.log2_diff_max_min_luma_coding_block_size != + sps->log2_diff_max_min_luma_coding_block_size || + o.bit_depth_luma_minus8 != sps->bit_depth_luma_minus8) { + base::EraseIf(active_pps_, [&](const auto& kv) { + return kv.second->pps_seq_parameter_set_id == *sps_id; + }); + } + } active_sps_[*sps_id] = std::move(sps); return res;