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() { ...@@ -650,7 +650,7 @@ bool VTVideoDecodeAccelerator::ConfigureDecoder() {
nalu_data_sizes.reserve(3); nalu_data_sizes.reserve(3);
nalu_data_ptrs.push_back(&active_sps_.front()); nalu_data_ptrs.push_back(&active_sps_.front());
nalu_data_sizes.push_back(active_sps_.size()); 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_ptrs.push_back(&active_spsext_.front());
nalu_data_sizes.push_back(active_spsext_.size()); nalu_data_sizes.push_back(active_spsext_.size());
} }
...@@ -773,8 +773,9 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer, ...@@ -773,8 +773,9 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
return; return;
} }
switch (nalu.nal_unit_type) { switch (nalu.nal_unit_type) {
case H264NALU::kSPS: case H264NALU::kSPS: {
result = parser_.ParseSPS(&last_sps_id_); int sps_id = -1;
result = parser_.ParseSPS(&sps_id);
if (result == H264Parser::kUnsupportedStream) { if (result == H264Parser::kUnsupportedStream) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR, "Unsupported SPS"); WriteToMediaLog(MediaLog::MEDIALOG_ERROR, "Unsupported SPS");
NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM); NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
...@@ -785,16 +786,27 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer, ...@@ -785,16 +786,27 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM); NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
return; return;
} }
last_sps_.assign(nalu.data, nalu.data + nalu.size); seen_sps_[sps_id].assign(nalu.data, nalu.data + nalu.size);
last_spsext_.clear(); seen_spsext_.erase(sps_id);
break; break;
}
case H264NALU::kSPSExt: case H264NALU::kSPSExt: {
last_spsext_.assign(nalu.data, nalu.data + nalu.size); 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; break;
}
case H264NALU::kPPS: case H264NALU::kPPS: {
result = parser_.ParsePPS(&last_pps_id_); int pps_id = -1;
result = parser_.ParsePPS(&pps_id);
if (result == H264Parser::kUnsupportedStream) { if (result == H264Parser::kUnsupportedStream) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR, "Unsupported PPS"); WriteToMediaLog(MediaLog::MEDIALOG_ERROR, "Unsupported PPS");
NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM); NotifyError(PLATFORM_FAILURE, SFT_UNSUPPORTED_STREAM);
...@@ -805,8 +817,9 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer, ...@@ -805,8 +817,9 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM); NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
return; return;
} }
last_pps_.assign(nalu.data, nalu.data + nalu.size); seen_pps_[pps_id].assign(nalu.data, nalu.data + nalu.size);
break; break;
}
case H264NALU::kSliceDataA: case H264NALU::kSliceDataA:
case H264NALU::kSliceDataB: case H264NALU::kSliceDataB:
...@@ -833,7 +846,6 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer, ...@@ -833,7 +846,6 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
} }
// Lookup SPS and PPS. // 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); const H264PPS* pps = parser_.GetPPS(slice_hdr.pic_parameter_set_id);
if (!pps) { if (!pps) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR, WriteToMediaLog(MediaLog::MEDIALOG_ERROR,
...@@ -842,7 +854,6 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer, ...@@ -842,7 +854,6 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
return; return;
} }
DCHECK_EQ(pps->seq_parameter_set_id, last_sps_id_);
const H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); const H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
if (!sps) { if (!sps) {
WriteToMediaLog(MediaLog::MEDIALOG_ERROR, WriteToMediaLog(MediaLog::MEDIALOG_ERROR,
...@@ -852,11 +863,12 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer, ...@@ -852,11 +863,12 @@ void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
} }
// Record the configuration. // Record the configuration.
// TODO(sandersd): Ideally this would be skipped if we know there DCHECK(seen_pps_.count(slice_hdr.pic_parameter_set_id));
// have not been any parameter sets since the last frame. DCHECK(seen_sps_.count(pps->seq_parameter_set_id));
active_sps_ = last_sps_; active_sps_ = seen_sps_[slice_hdr.pic_parameter_set_id];
active_spsext_ = last_spsext_; // Note: SPS extension lookup may create an empty entry.
active_pps_ = last_pps_; 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 // Compute and store frame properties. |image_size| gets filled in
// later, since it comes from the decoder configuration. // later, since it comes from the decoder configuration.
......
...@@ -243,26 +243,23 @@ class VTVideoDecodeAccelerator : public VideoDecodeAccelerator, ...@@ -243,26 +243,23 @@ class VTVideoDecodeAccelerator : public VideoDecodeAccelerator,
base::ScopedCFTypeRef<VTDecompressionSessionRef> session_; base::ScopedCFTypeRef<VTDecompressionSessionRef> session_;
H264Parser parser_; H264Parser parser_;
// Last SPS and PPS seen in the bitstream. // SPSs and PPSs seen in the bitstream.
// std::map<int, std::vector<uint8_t>> seen_sps_;
// TODO(sandersd): Keep a map from ID to last SPS/PPS, for streams that std::map<int, std::vector<uint8_t>> seen_spsext_;
// maintain multiple active configurations. (I've never seen such a stream.) std::map<int, std::vector<uint8_t>> seen_pps_;
int last_sps_id_ = -1;
int last_pps_id_ = -1; // SPS and PPS most recently activated by an IDR.
std::vector<uint8_t> last_sps_; // TODO(sandersd): Enable configuring with multiple PPSs.
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.
std::vector<uint8_t> active_sps_; std::vector<uint8_t> active_sps_;
std::vector<uint8_t> active_spsext_; std::vector<uint8_t> active_spsext_;
std::vector<uint8_t> active_pps_; 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_sps_;
std::vector<uint8_t> configured_spsext_; std::vector<uint8_t> configured_spsext_;
std::vector<uint8_t> configured_pps_; std::vector<uint8_t> configured_pps_;
// Visible rect the decoder is configured to use.
gfx::Size configured_size_; gfx::Size configured_size_;
bool waiting_for_idr_ = true; bool waiting_for_idr_ = true;
......
...@@ -354,6 +354,8 @@ bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream, ...@@ -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 (!sps.empty() && sps != last_sps_) {
if (!last_sps_.empty()) { if (!last_sps_.empty()) {
// Flag configuration changes after we see an IDR slice. // Flag configuration changes after we see an IDR slice.
......
...@@ -1219,6 +1219,19 @@ H264Parser::Result H264Parser::ParsePPS(int* pps_id) { ...@@ -1219,6 +1219,19 @@ H264Parser::Result H264Parser::ParsePPS(int* pps_id) {
return kOk; 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( H264Parser::Result H264Parser::ParseRefPicListModification(
int num_ref_idx_active_minus1, int num_ref_idx_active_minus1,
H264ModificationOfPicNum* ref_list_mods) { H264ModificationOfPicNum* ref_list_mods) {
......
...@@ -466,6 +466,9 @@ class MEDIA_EXPORT H264Parser { ...@@ -466,6 +466,9 @@ class MEDIA_EXPORT H264Parser {
Result ParseSPS(int* sps_id); Result ParseSPS(int* sps_id);
Result ParsePPS(int* pps_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 // Return a pointer to SPS/PPS with given |sps_id|/|pps_id| or NULL if not
// present. // present.
const H264SPS* GetSPS(int sps_id) const; 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