Commit 60090437 authored by Dan Sanders's avatar Dan Sanders Committed by Commit Bot

[media] VTVDA: Activate selected (rather than last) parameter sets.

Prior to this change, VTVDA activated the most recently seen sequence
and picture parameter sets (SPS and PPS) at IDR slices.

With this change it will use the SPS and PPS indicated by the IDR slice
header.

Bug: 988555
Change-Id: Id197545558529abc30fb64c9e638baf0b57f29c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1838688Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704319}
parent f165b1e3
......@@ -650,7 +650,7 @@ bool VTVideoDecodeAccelerator::ConfigureDecoder() {
nalu_data_sizes.reserve(3);
nalu_data_ptrs.push_back(&active_sps_.front());
nalu_data_sizes.push_back(active_sps_.size());
if (!last_spsext_.empty()) {
if (!active_spsext_.empty()) {
nalu_data_ptrs.push_back(&active_spsext_.front());
nalu_data_sizes.push_back(active_spsext_.size());
}
......@@ -773,8 +773,9 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
return;
}
switch (nalu.nal_unit_type) {
case H264NALU::kSPS:
result = parser_.ParseSPS(&last_sps_id_);
case H264NALU::kSPS: {
int sps_id = -1;
result = parser_.ParseSPS(&sps_id);
if (result == H264Parser::kUnsupportedStream) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR, "Unsupported SPS");
NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
......@@ -785,16 +786,27 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
return;
}
last_sps_.assign(nalu.data, nalu.data + nalu.size);
last_spsext_.clear();
seen_sps_[sps_id].assign(nalu.data, nalu.data + nalu.size);
seen_spsext_.erase(sps_id);
break;
}
case H264NALU::kSPSExt:
last_spsext_.assign(nalu.data, nalu.data + nalu.size);
case H264NALU::kSPSExt: {
int sps_id = -1;
result = parser_.ParseSPSExt(&sps_id);
if (result != H264Parser::kOk) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR,
"Could not parse SPS extension");
NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
return;
}
seen_spsext_[sps_id].assign(nalu.data, nalu.data + nalu.size);
break;
}
case H264NALU::kPPS:
result = parser_.ParsePPS(&last_pps_id_);
case H264NALU::kPPS: {
int pps_id = -1;
result = parser_.ParsePPS(&pps_id);
if (result == H264Parser::kUnsupportedStream) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR, "Unsupported PPS");
NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
......@@ -805,8 +817,9 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
return;
}
last_pps_.assign(nalu.data, nalu.data + nalu.size);
seen_pps_[pps_id].assign(nalu.data, nalu.data + nalu.size);
break;
}
case H264NALU::kSliceDataA:
case H264NALU::kSliceDataB:
......@@ -833,7 +846,6 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
}
// Lookup SPS and PPS.
DCHECK_EQ(slice_hdr.pic_parameter_set_id, last_pps_id_);
const H264PPS* pps = parser_.GetPPS(slice_hdr.pic_parameter_set_id);
if (!pps) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR,
......@@ -842,7 +854,6 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
return;
}
DCHECK_EQ(pps->seq_parameter_set_id, last_sps_id_);
const H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
if (!sps) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR,
......@@ -852,11 +863,12 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
}
// Record the configuration.
// TODO(sandersd): Ideally this would be skipped if we know there
// have not been any parameter sets since the last frame.
active_sps_ = last_sps_;
active_spsext_ = last_spsext_;
active_pps_ = last_pps_;
DCHECK(seen_pps_.count(slice_hdr.pic_parameter_set_id));
DCHECK(seen_sps_.count(pps->seq_parameter_set_id));
active_sps_ = seen_sps_[slice_hdr.pic_parameter_set_id];
// Note: SPS extension lookup may create an empty entry.
active_spsext_ = seen_spsext_[slice_hdr.pic_parameter_set_id];
active_pps_ = seen_pps_[pps->seq_parameter_set_id];
// Compute and store frame properties. |image_size| gets filled in
// later, since it comes from the decoder configuration.
......
......@@ -243,26 +243,23 @@ class VTVideoDecodeAccelerator : public VideoDecodeAccelerator,
base::ScopedCFTypeRef<VTDecompressionSessionRef> session_;
H264Parser parser_;
// Last SPS and PPS seen in the bitstream.
//
// TODO(sandersd): Keep a map from ID to last SPS/PPS, for streams that
// maintain multiple active configurations. (I've never seen such a stream.)
int last_sps_id_ = -1;
int last_pps_id_ = -1;
std::vector<uint8_t> last_sps_;
std::vector<uint8_t> last_spsext_;
std::vector<uint8_t> last_pps_;
// Last SPS and PPS referenced by a slice. In practice these will be the same
// as the last seen values, unless the bitstream is malformatted.
// SPSs and PPSs seen in the bitstream.
std::map<int, std::vector<uint8_t>> seen_sps_;
std::map<int, std::vector<uint8_t>> seen_spsext_;
std::map<int, std::vector<uint8_t>> seen_pps_;
// SPS and PPS most recently activated by an IDR.
// TODO(sandersd): Enable configuring with multiple PPSs.
std::vector<uint8_t> active_sps_;
std::vector<uint8_t> active_spsext_;
std::vector<uint8_t> active_pps_;
// Last SPS and PPS the decoder was confgured with.
// SPS and PPS the decoder is currently confgured with.
std::vector<uint8_t> configured_sps_;
std::vector<uint8_t> configured_spsext_;
std::vector<uint8_t> configured_pps_;
// Visible rect the decoder is configured to use.
gfx::Size configured_size_;
bool waiting_for_idr_ = true;
......
......@@ -354,6 +354,8 @@ bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream,
}
}
// TODO(sandersd): Update to match logic in VTVDA that tracks activated rather
// than most recent SPS and PPS.
if (!sps.empty() && sps != last_sps_) {
if (!last_sps_.empty()) {
// Flag configuration changes after we see an IDR slice.
......
......@@ -1219,6 +1219,19 @@ H264Parser::Result H264Parser::ParsePPS(int* pps_id) {
return kOk;
}
H264Parser::Result H264Parser::ParseSPSExt(int* sps_id) {
// See 7.4.2.1.
int local_sps_id = -1;
*sps_id = -1;
READ_UE_OR_RETURN(&local_sps_id);
TRUE_OR_RETURN(local_sps_id < 32);
*sps_id = local_sps_id;
return kOk;
}
H264Parser::Result H264Parser::ParseRefPicListModification(
int num_ref_idx_active_minus1,
H264ModificationOfPicNum* ref_list_mods) {
......
......@@ -466,6 +466,9 @@ class MEDIA_EXPORT H264Parser {
Result ParseSPS(int* sps_id);
Result ParsePPS(int* pps_id);
// Parses the SPS ID from the SPSExt, but otherwise does nothing.
Result ParseSPSExt(int* sps_id);
// Return a pointer to SPS/PPS with given |sps_id|/|pps_id| or NULL if not
// present.
const H264SPS* GetSPS(int sps_id) const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment