Commit 689cd428 authored by Xiaohan Wang's avatar Xiaohan Wang Committed by Commit Bot

media: Add kError to DemuxerStream::Status

Some DemuxerStream could hit non-recoverable fatal errors. For example,
DecryptingDemuxerStream cannot decrypt a buffer because the CDM was
crashed.

This CL adds a new kError status to DemuxerStream::Status to indicate
such conditions.

BUG=730766
TEST=New unittests added.

Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Ia07e14662d7da852f712076dcc94aed1900aaba3
Reviewed-on: https://chromium-review.googlesource.com/598702
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarMatthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491960}
parent 6869f052
...@@ -51,11 +51,13 @@ class MEDIA_EXPORT DemuxerStream { ...@@ -51,11 +51,13 @@ class MEDIA_EXPORT DemuxerStream {
// when this status is returned. // when this status is returned.
// This will only be returned if SupportsConfigChanges() // This will only be returned if SupportsConfigChanges()
// returns 'true' for this DemuxerStream. // returns 'true' for this DemuxerStream.
// kError : Unexpected fatal error happened. Playback should fail.
enum Status { enum Status {
kOk, kOk,
kAborted, kAborted,
kConfigChanged, kConfigChanged,
kStatusMax = kConfigChanged, kError,
kStatusMax = kError,
}; };
// Request a buffer to returned via the provided callback. // Request a buffer to returned via the provided callback.
......
...@@ -140,6 +140,13 @@ void FakeDemuxerStream::Reset() { ...@@ -140,6 +140,13 @@ void FakeDemuxerStream::Reset() {
base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
} }
void FakeDemuxerStream::Error() {
read_to_hold_ = -1;
if (!read_cb_.is_null())
base::ResetAndReturn(&read_cb_).Run(kError, nullptr);
}
void FakeDemuxerStream::SeekToStart() { void FakeDemuxerStream::SeekToStart() {
Reset(); Reset();
Initialize(); Initialize();
......
...@@ -59,6 +59,10 @@ class FakeDemuxerStream : public DemuxerStream { ...@@ -59,6 +59,10 @@ class FakeDemuxerStream : public DemuxerStream {
// always clears |hold_next_read_|. // always clears |hold_next_read_|.
void Reset(); void Reset();
// Satisfies the pending read (if any) with kError and NULL. This call
// always clears |hold_next_read_|.
void Error();
// Reset() this demuxer stream and set the reading position to the start of // Reset() this demuxer stream and set the reading position to the start of
// the stream. // the stream.
void SeekToStart(); void SeekToStart();
......
...@@ -42,13 +42,7 @@ class FakeDemuxerStreamTest : public testing::Test { ...@@ -42,13 +42,7 @@ class FakeDemuxerStreamTest : public testing::Test {
num_buffers_received_++; num_buffers_received_++;
} }
enum ReadResult { enum ReadResult { OK, ABORTED, CONFIG_CHANGED, READ_ERROR, EOS, PENDING };
OK,
ABORTED,
CONFIG_CHANGED,
EOS,
PENDING
};
void EnterNormalReadState() { void EnterNormalReadState() {
stream_.reset( stream_.reset(
...@@ -87,6 +81,12 @@ class FakeDemuxerStreamTest : public testing::Test { ...@@ -87,6 +81,12 @@ class FakeDemuxerStreamTest : public testing::Test {
EXPECT_FALSE(buffer_.get()); EXPECT_FALSE(buffer_.get());
break; break;
case READ_ERROR:
EXPECT_FALSE(read_pending_);
EXPECT_EQ(DemuxerStream::kError, status_);
EXPECT_FALSE(buffer_.get());
break;
case EOS: case EOS:
EXPECT_FALSE(read_pending_); EXPECT_FALSE(read_pending_);
EXPECT_EQ(DemuxerStream::kOk, status_); EXPECT_EQ(DemuxerStream::kOk, status_);
...@@ -137,6 +137,16 @@ class FakeDemuxerStreamTest : public testing::Test { ...@@ -137,6 +137,16 @@ class FakeDemuxerStreamTest : public testing::Test {
ExpectReadResult(ABORTED); ExpectReadResult(ABORTED);
} }
void Error() {
bool had_read_pending = read_pending_;
stream_->Error();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(read_pending_);
if (had_read_pending)
ExpectReadResult(READ_ERROR);
}
void ReadAllBuffers(int num_configs, int num_buffers_in_one_config) { void ReadAllBuffers(int num_configs, int num_buffers_in_one_config) {
DCHECK_EQ(0, num_buffers_received_); DCHECK_EQ(0, num_buffers_received_);
for (int i = 0; i < num_configs; ++i) { for (int i = 0; i < num_configs; ++i) {
...@@ -256,6 +266,35 @@ TEST_F(FakeDemuxerStreamTest, Reset_BeforeEOS) { ...@@ -256,6 +266,35 @@ TEST_F(FakeDemuxerStreamTest, Reset_BeforeEOS) {
ReadAndExpect(EOS); ReadAndExpect(EOS);
} }
TEST_F(FakeDemuxerStreamTest, Error_Normal) {
EnterNormalReadState();
Error();
ReadAndExpect(OK);
}
TEST_F(FakeDemuxerStreamTest, Error_AfterHoldRead) {
EnterNormalReadState();
stream_->HoldNextRead();
Error();
ReadAndExpect(OK);
}
TEST_F(FakeDemuxerStreamTest, Error_BeforeConfigChanged) {
EnterNormalReadState();
stream_->HoldNextConfigChangeRead();
ReadUntilPending();
Error();
ReadAndExpect(CONFIG_CHANGED);
}
TEST_F(FakeDemuxerStreamTest, Error_BeforeEOS) {
EnterBeforeEOSState();
stream_->HoldNextRead();
ReadAndExpect(PENDING);
Error();
ReadAndExpect(EOS);
}
TEST_F(FakeDemuxerStreamTest, NoConfigChanges) { TEST_F(FakeDemuxerStreamTest, NoConfigChanges) {
stream_.reset( stream_.reset(
new FakeDemuxerStream(1, kNumBuffersInOneConfig, false)); new FakeDemuxerStream(1, kNumBuffersInOneConfig, false));
......
...@@ -595,14 +595,25 @@ void DecoderStream<StreamType>::OnBufferReady( ...@@ -595,14 +595,25 @@ void DecoderStream<StreamType>::OnBufferReady(
pending_buffers_.clear(); pending_buffers_.clear();
break; break;
case DemuxerStream::kAborted: case DemuxerStream::kAborted:
// |this| will read from the demuxer stream again in OnDecoderSelected() case DemuxerStream::kError:
// and receive a kAborted then. // Will read from the demuxer stream again in OnDecoderSelected().
pending_buffers_.clear(); pending_buffers_.clear();
break; break;
} }
return; return;
} }
if (status == DemuxerStream::kError) {
FUNCTION_DVLOG(1) << ": Demuxer stream read error!";
state_ = STATE_ERROR;
MEDIA_LOG(ERROR, media_log_)
<< GetStreamTypeString() << " demuxer stream read error!";
pending_buffers_.clear();
ready_outputs_.clear();
if (!read_cb_.is_null())
SatisfyRead(DECODE_ERROR, nullptr);
}
// Decoding has been stopped. // Decoding has been stopped.
if (state_ == STATE_ERROR) { if (state_ == STATE_ERROR) {
DCHECK(read_cb_.is_null()); DCHECK(read_cb_.is_null());
......
...@@ -202,6 +202,7 @@ class DecryptingAudioDecoderTest : public testing::Test { ...@@ -202,6 +202,7 @@ class DecryptingAudioDecoderTest : public testing::Test {
decoder_->Decode(encrypted_buffer_, decoder_->Decode(encrypted_buffer_,
base::Bind(&DecryptingAudioDecoderTest::DecodeDone, base::Bind(&DecryptingAudioDecoderTest::DecodeDone,
base::Unretained(this))); base::Unretained(this)));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
......
...@@ -174,7 +174,7 @@ DecryptingDemuxerStream::~DecryptingDemuxerStream() { ...@@ -174,7 +174,7 @@ DecryptingDemuxerStream::~DecryptingDemuxerStream() {
void DecryptingDemuxerStream::DecryptBuffer( void DecryptingDemuxerStream::DecryptBuffer(
DemuxerStream::Status status, DemuxerStream::Status status,
const scoped_refptr<DecoderBuffer>& buffer) { const scoped_refptr<DecoderBuffer>& buffer) {
DVLOG(3) << __func__; DVLOG(3) << __func__ << ": status = " << status;
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDemuxerRead) << state_; DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
DCHECK(!read_cb_.is_null()); DCHECK(!read_cb_.is_null());
...@@ -204,10 +204,13 @@ void DecryptingDemuxerStream::DecryptBuffer( ...@@ -204,10 +204,13 @@ void DecryptingDemuxerStream::DecryptBuffer(
return; return;
} }
if (status == kAborted) { if (status == kAborted || status == kError) {
DVLOG(2) << "DoDecryptBuffer() - kAborted."; if (status == kError) {
MEDIA_LOG(ERROR, media_log_)
<< GetDisplayName() << ": demuxer stream read error.";
}
state_ = kIdle; state_ = kIdle;
base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); base::ResetAndReturn(&read_cb_).Run(status, nullptr);
return; return;
} }
...@@ -285,7 +288,7 @@ void DecryptingDemuxerStream::DeliverBuffer( ...@@ -285,7 +288,7 @@ void DecryptingDemuxerStream::DeliverBuffer(
MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": decrypt error"; MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": decrypt error";
pending_buffer_to_decrypt_ = NULL; pending_buffer_to_decrypt_ = NULL;
state_ = kIdle; state_ = kIdle;
base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); base::ResetAndReturn(&read_cb_).Run(kError, nullptr);
return; return;
} }
...@@ -330,8 +333,8 @@ void DecryptingDemuxerStream::OnKeyAdded() { ...@@ -330,8 +333,8 @@ void DecryptingDemuxerStream::OnKeyAdded() {
} }
if (state_ == kWaitingForKey) { if (state_ == kWaitingForKey) {
MEDIA_LOG(INFO, media_log_) << GetDisplayName() MEDIA_LOG(INFO, media_log_)
<< ": key added, resuming decrypt"; << GetDisplayName() << ": key was added, resuming decrypt";
state_ = kPendingDecrypt; state_ = kPendingDecrypt;
DecryptPendingBuffer(); DecryptPendingBuffer();
} }
......
...@@ -17,12 +17,15 @@ ...@@ -17,12 +17,15 @@
#include "media/base/gmock_callback_support.h" #include "media/base/gmock_callback_support.h"
#include "media/base/media_util.h" #include "media/base/media_util.h"
#include "media/base/mock_filters.h" #include "media/base/mock_filters.h"
#include "media/base/mock_media_log.h"
#include "media/base/test_helpers.h" #include "media/base/test_helpers.h"
#include "media/filters/decrypting_demuxer_stream.h" #include "media/filters/decrypting_demuxer_stream.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
using ::testing::_; using ::testing::_;
using ::testing::HasSubstr;
using ::testing::IsNull; using ::testing::IsNull;
using ::testing::InSequence;
using ::testing::Return; using ::testing::Return;
using ::testing::SaveArg; using ::testing::SaveArg;
using ::testing::StrictMock; using ::testing::StrictMock;
...@@ -217,11 +220,13 @@ class DecryptingDemuxerStreamTest : public testing::Test { ...@@ -217,11 +220,13 @@ class DecryptingDemuxerStreamTest : public testing::Test {
} }
void EnterWaitingForKeyState() { void EnterWaitingForKeyState() {
InSequence s;
EXPECT_CALL(*input_audio_stream_, Read(_)) EXPECT_CALL(*input_audio_stream_, Read(_))
.WillRepeatedly(ReturnBuffer(encrypted_buffer_)); .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _)) EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
.WillRepeatedly(RunCallback<2>(Decryptor::kNoKey, .WillRepeatedly(RunCallback<2>(Decryptor::kNoKey,
scoped_refptr<DecoderBuffer>())); scoped_refptr<DecoderBuffer>()));
EXPECT_MEDIA_LOG(HasSubstr("DecryptingDemuxerStream: no key for key ID"));
EXPECT_CALL(*this, OnWaitingForDecryptionKey()); EXPECT_CALL(*this, OnWaitingForDecryptionKey());
demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady, demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady,
base::Unretained(this))); base::Unretained(this)));
...@@ -254,7 +259,7 @@ class DecryptingDemuxerStreamTest : public testing::Test { ...@@ -254,7 +259,7 @@ class DecryptingDemuxerStreamTest : public testing::Test {
MOCK_METHOD0(OnWaitingForDecryptionKey, void(void)); MOCK_METHOD0(OnWaitingForDecryptionKey, void(void));
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
MediaLog media_log_; StrictMock<MockMediaLog> media_log_;
std::unique_ptr<DecryptingDemuxerStream> demuxer_stream_; std::unique_ptr<DecryptingDemuxerStream> demuxer_stream_;
std::unique_ptr<StrictMock<MockCdmContext>> cdm_context_; std::unique_ptr<StrictMock<MockCdmContext>> cdm_context_;
std::unique_ptr<StrictMock<MockDecryptor>> decryptor_; std::unique_ptr<StrictMock<MockDecryptor>> decryptor_;
...@@ -308,6 +313,7 @@ TEST_F(DecryptingDemuxerStreamTest, Initialize_CdmWithoutDecryptor) { ...@@ -308,6 +313,7 @@ TEST_F(DecryptingDemuxerStreamTest, Initialize_CdmWithoutDecryptor) {
AudioDecoderConfig input_config(kCodecVorbis, kSampleFormatPlanarF32, AudioDecoderConfig input_config(kCodecVorbis, kSampleFormatPlanarF32,
CHANNEL_LAYOUT_STEREO, 44100, CHANNEL_LAYOUT_STEREO, 44100,
EmptyExtraData(), AesCtrEncryptionScheme()); EmptyExtraData(), AesCtrEncryptionScheme());
EXPECT_MEDIA_LOG(HasSubstr("DecryptingDemuxerStream: no decryptor"));
InitializeAudioAndExpectStatus(input_config, DECODER_ERROR_NOT_SUPPORTED); InitializeAudioAndExpectStatus(input_config, DECODER_ERROR_NOT_SUPPORTED);
} }
...@@ -340,7 +346,8 @@ TEST_F(DecryptingDemuxerStreamTest, Read_DecryptError) { ...@@ -340,7 +346,8 @@ TEST_F(DecryptingDemuxerStreamTest, Read_DecryptError) {
EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _)) EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
.WillRepeatedly(RunCallback<2>(Decryptor::kError, .WillRepeatedly(RunCallback<2>(Decryptor::kError,
scoped_refptr<DecoderBuffer>())); scoped_refptr<DecoderBuffer>()));
ReadAndExpectBufferReadyWith(DemuxerStream::kAborted, NULL); EXPECT_MEDIA_LOG(HasSubstr("DecryptingDemuxerStream: decrypt error"));
ReadAndExpectBufferReadyWith(DemuxerStream::kError, nullptr);
} }
// Test the case where the input is an end-of-stream buffer. // Test the case where the input is an end-of-stream buffer.
...@@ -362,6 +369,8 @@ TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DuringWaitingForKey) { ...@@ -362,6 +369,8 @@ TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DuringWaitingForKey) {
Initialize(); Initialize();
EnterWaitingForKeyState(); EnterWaitingForKeyState();
EXPECT_MEDIA_LOG(
HasSubstr("DecryptingDemuxerStream: key was added, resuming decrypt"));
EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _)) EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
.WillRepeatedly(RunCallback<2>(Decryptor::kSuccess, decrypted_buffer_)); .WillRepeatedly(RunCallback<2>(Decryptor::kSuccess, decrypted_buffer_));
EXPECT_CALL(*this, BufferReady(DemuxerStream::kOk, decrypted_buffer_)); EXPECT_CALL(*this, BufferReady(DemuxerStream::kOk, decrypted_buffer_));
...@@ -375,6 +384,9 @@ TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DuringPendingDecrypt) { ...@@ -375,6 +384,9 @@ TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DuringPendingDecrypt) {
Initialize(); Initialize();
EnterPendingDecryptState(); EnterPendingDecryptState();
EXPECT_MEDIA_LOG(HasSubstr("DecryptingDemuxerStream: no key for key ID"));
EXPECT_MEDIA_LOG(
HasSubstr("DecryptingDemuxerStream: key was added, resuming decrypt"));
EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _)) EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
.WillRepeatedly(RunCallback<2>(Decryptor::kSuccess, decrypted_buffer_)); .WillRepeatedly(RunCallback<2>(Decryptor::kSuccess, decrypted_buffer_));
EXPECT_CALL(*this, BufferReady(DemuxerStream::kOk, decrypted_buffer_)); EXPECT_CALL(*this, BufferReady(DemuxerStream::kOk, decrypted_buffer_));
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "media/base/fake_demuxer_stream.h" #include "media/base/fake_demuxer_stream.h"
#include "media/base/gmock_callback_support.h" #include "media/base/gmock_callback_support.h"
#include "media/base/mock_filters.h" #include "media/base/mock_filters.h"
#include "media/base/mock_media_log.h"
#include "media/base/test_helpers.h" #include "media/base/test_helpers.h"
#include "media/base/timestamp_constants.h" #include "media/base/timestamp_constants.h"
#include "media/filters/decoder_stream.h" #include "media/filters/decoder_stream.h"
...@@ -24,6 +25,8 @@ ...@@ -24,6 +25,8 @@
using ::testing::_; using ::testing::_;
using ::testing::AnyNumber; using ::testing::AnyNumber;
using ::testing::Assign; using ::testing::Assign;
using ::testing::HasSubstr;
using ::testing::InSequence;
using ::testing::Invoke; using ::testing::Invoke;
using ::testing::InvokeWithoutArgs; using ::testing::InvokeWithoutArgs;
using ::testing::NiceMock; using ::testing::NiceMock;
...@@ -97,6 +100,11 @@ class VideoFrameStreamTest ...@@ -97,6 +100,11 @@ class VideoFrameStreamTest
EXPECT_CALL(*cdm_context_, GetDecryptor()) EXPECT_CALL(*cdm_context_, GetDecryptor())
.WillRepeatedly(Return(decryptor_.get())); .WillRepeatedly(Return(decryptor_.get()));
} }
// Covering most MediaLog messages for now.
// TODO(wolenetz/xhwang): Fix tests to have better MediaLog checking.
EXPECT_MEDIA_LOG(HasSubstr("video")).Times(AnyNumber());
EXPECT_MEDIA_LOG(HasSubstr("decryptor")).Times(AnyNumber());
} }
~VideoFrameStreamTest() { ~VideoFrameStreamTest() {
...@@ -322,6 +330,7 @@ class VideoFrameStreamTest ...@@ -322,6 +330,7 @@ class VideoFrameStreamTest
case DECRYPTOR_NO_KEY: case DECRYPTOR_NO_KEY:
if (GetParam().is_encrypted && GetParam().has_decryptor) { if (GetParam().is_encrypted && GetParam().has_decryptor) {
EXPECT_MEDIA_LOG(HasSubstr("no key for key ID"));
EXPECT_CALL(*this, OnWaitingForDecryptionKey()); EXPECT_CALL(*this, OnWaitingForDecryptionKey());
has_no_key_ = true; has_no_key_ = true;
} }
...@@ -403,7 +412,7 @@ class VideoFrameStreamTest ...@@ -403,7 +412,7 @@ class VideoFrameStreamTest
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
MediaLog media_log_; StrictMock<MockMediaLog> media_log_;
std::unique_ptr<VideoFrameStream> video_frame_stream_; std::unique_ptr<VideoFrameStream> video_frame_stream_;
std::unique_ptr<FakeDemuxerStream> demuxer_stream_; std::unique_ptr<FakeDemuxerStream> demuxer_stream_;
std::unique_ptr<StrictMock<MockCdmContext>> cdm_context_; std::unique_ptr<StrictMock<MockCdmContext>> cdm_context_;
...@@ -617,6 +626,25 @@ TEST_P(VideoFrameStreamTest, Read_DuringEndOfStreamDecode) { ...@@ -617,6 +626,25 @@ TEST_P(VideoFrameStreamTest, Read_DuringEndOfStreamDecode) {
frame_read_->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)); frame_read_->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM));
} }
TEST_P(VideoFrameStreamTest, Read_DemuxerStreamReadError) {
Initialize();
EnterPendingState(DEMUXER_READ_NORMAL);
InSequence s;
if (GetParam().is_encrypted && GetParam().has_decryptor) {
EXPECT_MEDIA_LOG(
HasSubstr("DecryptingDemuxerStream: demuxer stream read error"));
}
EXPECT_MEDIA_LOG(HasSubstr("video demuxer stream read error"));
demuxer_stream_->Error();
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(pending_read_);
EXPECT_EQ(last_read_status_, VideoFrameStream::DECODE_ERROR);
}
// No Reset() before initialization is successfully completed. // No Reset() before initialization is successfully completed.
TEST_P(VideoFrameStreamTest, Reset_AfterInitialization) { TEST_P(VideoFrameStreamTest, Reset_AfterInitialization) {
Initialize(); Initialize();
......
...@@ -271,6 +271,10 @@ void DemuxerStreamAdapter::OnNewBuffer( ...@@ -271,6 +271,10 @@ void DemuxerStreamAdapter::OnNewBuffer(
DCHECK(!input); DCHECK(!input);
SendReadAck(); SendReadAck();
return; return;
case DemuxerStream::kError:
// Currently kError can only happen because of DECRYPTION_ERROR.
OnFatalError(DECRYPTION_ERROR);
return;
case DemuxerStream::kConfigChanged: case DemuxerStream::kConfigChanged:
// TODO(erickung): Notify controller of new decoder config, just in case // TODO(erickung): Notify controller of new decoder config, just in case
// that will require remoting to be shutdown (due to known // that will require remoting to be shutdown (due to known
......
...@@ -577,6 +577,7 @@ base::Optional<DemuxerStream::Status> ToDemuxerStreamStatus( ...@@ -577,6 +577,7 @@ base::Optional<DemuxerStream::Status> ToDemuxerStreamStatus(
CASE_RETURN_OTHER(kOk); CASE_RETURN_OTHER(kOk);
CASE_RETURN_OTHER(kAborted); CASE_RETURN_OTHER(kAborted);
CASE_RETURN_OTHER(kConfigChanged); CASE_RETURN_OTHER(kConfigChanged);
CASE_RETURN_OTHER(kError);
} }
return base::nullopt; // Not a 'default' to ensure compile-time checks. return base::nullopt; // Not a 'default' to ensure compile-time checks.
} }
...@@ -589,6 +590,7 @@ ToProtoDemuxerStreamStatus(DemuxerStream::Status value) { ...@@ -589,6 +590,7 @@ ToProtoDemuxerStreamStatus(DemuxerStream::Status value) {
CASE_RETURN_OTHER(kOk); CASE_RETURN_OTHER(kOk);
CASE_RETURN_OTHER(kAborted); CASE_RETURN_OTHER(kAborted);
CASE_RETURN_OTHER(kConfigChanged); CASE_RETURN_OTHER(kConfigChanged);
CASE_RETURN_OTHER(kError);
} }
return base::nullopt; // Not a 'default' to ensure compile-time checks. return base::nullopt; // Not a 'default' to ensure compile-time checks.
} }
......
...@@ -363,6 +363,7 @@ message DemuxerStreamReadUntilCallback { ...@@ -363,6 +363,7 @@ message DemuxerStreamReadUntilCallback {
kOk = 0; kOk = 0;
kAborted = 1; kAborted = 1;
kConfigChanged = 2; kConfigChanged = 2;
kError = 3;
}; };
optional Status status = 1; optional Status status = 1;
......
...@@ -336,6 +336,7 @@ void MediaStream::CompleteRead(DemuxerStream::Status status) { ...@@ -336,6 +336,7 @@ void MediaStream::CompleteRead(DemuxerStream::Status status) {
base::ResetAndReturn(&read_complete_callback_).Run(status, nullptr); base::ResetAndReturn(&read_complete_callback_).Run(status, nullptr);
return; return;
case DemuxerStream::kAborted: case DemuxerStream::kAborted:
case DemuxerStream::kError:
base::ResetAndReturn(&read_complete_callback_).Run(status, nullptr); base::ResetAndReturn(&read_complete_callback_).Run(status, nullptr);
return; return;
case DemuxerStream::kOk: case DemuxerStream::kOk:
......
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