Commit 6572a39c authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Reuse decryptor after video decoder re-initialization

Previously FuchsiaVideoDecoder was was destroying decryptor when
re-initializing. This approach wasn't working well because the buffer
collection shared between decryptor and decoder is being torn down when
decryptor is destroyed, which causes the decoder to fail as well. To
avoid this issue FuchsiaVideoDecoder now reuses the decryptor after
re-initialization.

Bug: 1003529
Change-Id: Ie90d4e5f9d4bbe5d96dafcfc69d19f314080c05c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1819945
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Commit-Queue: Yuchen Liu <yucliu@chromium.org>
Reviewed-by: default avatarYuchen Liu <yucliu@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Auto-Submit: Sergey Ulanov <sergeyu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699874}
parent 7993f51a
...@@ -179,6 +179,8 @@ class FuchsiaVideoDecoder : public VideoDecoder, ...@@ -179,6 +179,8 @@ class FuchsiaVideoDecoder : public VideoDecoder,
int GetMaxDecodeRequests() const override; int GetMaxDecodeRequests() const override;
private: private:
bool InitializeDecryptor(CdmContext* cdm_context);
// FuchsiaSecureStreamDecryptor::Client implementation. // FuchsiaSecureStreamDecryptor::Client implementation.
void OnDecryptorOutputPacket(StreamProcessorHelper::IoPacket packet) override; void OnDecryptorOutputPacket(StreamProcessorHelper::IoPacket packet) override;
void OnDecryptorEndOfStreamPacket() override; void OnDecryptorEndOfStreamPacket() override;
...@@ -324,31 +326,14 @@ void FuchsiaVideoDecoder::Initialize(const VideoDecoderConfig& config, ...@@ -324,31 +326,14 @@ void FuchsiaVideoDecoder::Initialize(const VideoDecoderConfig& config,
InitCB init_cb, InitCB init_cb,
const OutputCB& output_cb, const OutputCB& output_cb,
const WaitingCB& waiting_cb) { const WaitingCB& waiting_cb) {
auto done_callback = BindToCurrentLoop(std::move(init_cb)); DCHECK(decode_callbacks_.empty());
if (!DropInputQueue(DecodeStatus::ABORTED))
return;
if (config.is_encrypted()) {
// Caller makes sure |cdm_context| is available if the stream is encrypted.
if (!cdm_context) {
LOG(ERROR) << "No cdm context for encrypted stream.";
std::move(done_callback).Run(false);
return;
}
// If Cdm is not FuchsiaCdm then fail initialization to allow decoder auto done_callback = BindToCurrentLoop(std::move(init_cb));
// selector to choose DecryptingDemuxerStream, which will handle the
// decryption and pass the clear stream to this decoder.
FuchsiaCdmContext* fuchsia_cdm = cdm_context->GetFuchsiaCdmContext();
if (!fuchsia_cdm) {
DVLOG(1) << "FuchsiaVideoDecoder is compatible only with Fuchsia CDM.";
std::move(done_callback).Run(false);
return;
}
decryptor_ = fuchsia_cdm->CreateSecureDecryptor(this); // There should be no pending decode request, so DropInputQueue() is not
} // expected to fail.
bool result = DropInputQueue(DecodeStatus::ABORTED);
DCHECK(result);
output_cb_ = output_cb; output_cb_ = output_cb;
container_pixel_aspect_ratio_ = config.GetPixelAspectRatio(); container_pixel_aspect_ratio_ = config.GetPixelAspectRatio();
...@@ -356,28 +341,39 @@ void FuchsiaVideoDecoder::Initialize(const VideoDecoderConfig& config, ...@@ -356,28 +341,39 @@ void FuchsiaVideoDecoder::Initialize(const VideoDecoderConfig& config,
// If we already have |decoder_| that was initializes for the same codec then // If we already have |decoder_| that was initializes for the same codec then
// keep using it. // keep using it.
if (decoder_ && current_codec_ == config.codec()) { if (decoder_ && current_codec_ == config.codec()) {
// Input buffers can be in one of the following states here: bool have_decryptor = decryptor_ != nullptr;
// 1. Input buffer constraints are empty, i.e. OnInputConstraints() event if (have_decryptor != config.is_encrypted()) {
// hasn't been received yet. Input buffers will be allocated once // If decryption mode has changed then we need to re-initialize input
// OnInputConstraints() is received. // buffers.
// 2. Input buffers are being created. ReleaseInputBuffers();
// 3. Input buffers exist. decryptor_.reset();
// 4. Input buffers were destroyed by DropInputQueue() call above (which is
// required for encrypted streams). // Initialize decryptor for encrypted streams.
// if (config.is_encrypted() && !InitializeDecryptor(cdm_context)) {
// In the last case we need to re-initialize input buffers by calling std::move(done_callback).Run(false);
// OnInputConstraints(). return;
if (decoder_input_constraints_.has_value() && }
!input_buffer_collection_creator_ && !input_buffer_collection_) {
OnInputConstraints(std::move(decoder_input_constraints_).value()); // If we haven't received input constraints yet then input buffers will be
// initialized later when OnInputConstraints() is received.
if (decoder_input_constraints_.has_value()) {
OnInputConstraints(std::move(decoder_input_constraints_).value());
}
} }
std::move(done_callback).Run(true); std::move(done_callback).Run(true);
return; return;
} }
decryptor_.reset();
decoder_.Unbind(); decoder_.Unbind();
// Initialize decryptor for encrypted streams.
if (config.is_encrypted() && !InitializeDecryptor(cdm_context)) {
std::move(done_callback).Run(false);
return;
}
// Reset IO buffers since we won't be able to re-use them. // Reset IO buffers since we won't be able to re-use them.
ReleaseInputBuffers(); ReleaseInputBuffers();
ReleaseOutputBuffers(); ReleaseOutputBuffers();
...@@ -483,6 +479,29 @@ int FuchsiaVideoDecoder::GetMaxDecodeRequests() const { ...@@ -483,6 +479,29 @@ int FuchsiaVideoDecoder::GetMaxDecodeRequests() const {
return num_input_buffers_ + 1; return num_input_buffers_ + 1;
} }
bool FuchsiaVideoDecoder::InitializeDecryptor(CdmContext* cdm_context) {
DCHECK(!decryptor_);
// Caller makes sure |cdm_context| is available if the stream is encrypted.
if (!cdm_context) {
DLOG(ERROR) << "No cdm context for encrypted stream.";
return false;
}
// If Cdm is not FuchsiaCdm then fail initialization to allow decoder
// selector to choose DecryptingDemuxerStream, which will handle the
// decryption and pass the clear stream to this decoder.
FuchsiaCdmContext* fuchsia_cdm = cdm_context->GetFuchsiaCdmContext();
if (!fuchsia_cdm) {
DLOG(ERROR) << "FuchsiaVideoDecoder is compatible only with Fuchsia CDM.";
return false;
}
decryptor_ = fuchsia_cdm->CreateSecureDecryptor(this);
return true;
}
void FuchsiaVideoDecoder::OnDecryptorOutputPacket( void FuchsiaVideoDecoder::OnDecryptorOutputPacket(
StreamProcessorHelper::IoPacket packet) { StreamProcessorHelper::IoPacket packet) {
SendInputPacket(nullptr, std::move(packet)); SendInputPacket(nullptr, std::move(packet));
...@@ -917,11 +936,8 @@ bool FuchsiaVideoDecoder::DropInputQueue(DecodeStatus status) { ...@@ -917,11 +936,8 @@ bool FuchsiaVideoDecoder::DropInputQueue(DecodeStatus status) {
active_stream_ = false; active_stream_ = false;
} }
// Input buffers have to be re-initialized for encrypted streams. if (decryptor_)
if (decryptor_) { decryptor_->Reset();
decryptor_.reset();
ReleaseInputBuffers();
}
in_flight_input_packets_.clear(); in_flight_input_packets_.clear();
......
...@@ -403,6 +403,10 @@ void FuchsiaSecureStreamDecryptor::Decrypt( ...@@ -403,6 +403,10 @@ void FuchsiaSecureStreamDecryptor::Decrypt(
DecryptInternal(std::move(encrypted)); DecryptInternal(std::move(encrypted));
} }
void FuchsiaSecureStreamDecryptor::Reset() {
ResetStream();
}
void FuchsiaSecureStreamDecryptor::AllocateOutputBuffers( void FuchsiaSecureStreamDecryptor::AllocateOutputBuffers(
const fuchsia::media::StreamBufferConstraints& stream_constraints) { const fuchsia::media::StreamBufferConstraints& stream_constraints) {
if (complete_buffer_allocation_callback_) { if (complete_buffer_allocation_callback_) {
......
...@@ -126,6 +126,9 @@ class FuchsiaSecureStreamDecryptor : public FuchsiaStreamDecryptorBase { ...@@ -126,6 +126,9 @@ class FuchsiaSecureStreamDecryptor : public FuchsiaStreamDecryptorBase {
void Decrypt(scoped_refptr<DecoderBuffer> encrypted); void Decrypt(scoped_refptr<DecoderBuffer> encrypted);
// Drops all pending decryption requests.
void Reset();
private: private:
// StreamProcessorHelper::Client overrides. // StreamProcessorHelper::Client overrides.
void AllocateOutputBuffers(const fuchsia::media::StreamBufferConstraints& void AllocateOutputBuffers(const fuchsia::media::StreamBufferConstraints&
......
...@@ -125,9 +125,12 @@ void StreamProcessorHelper::Reset() { ...@@ -125,9 +125,12 @@ void StreamProcessorHelper::Reset() {
return; return;
} }
processor_->CloseCurrentStream(stream_lifetime_ordinal_, if (processor_ && active_stream_) {
/*release_input_buffers=*/false, processor_->CloseCurrentStream(stream_lifetime_ordinal_,
/*release_output_buffers=*/false); /*release_input_buffers=*/false,
/*release_output_buffers=*/false);
}
stream_lifetime_ordinal_ += 2; stream_lifetime_ordinal_ += 2;
active_stream_ = false; active_stream_ = false;
input_packets_.clear(); input_packets_.clear();
......
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