summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-27 20:36:10 +0000
committerfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-27 20:36:10 +0000
commitab34561dd992607626f7b7c7ee06d429de55df04 (patch)
treeec9f032f24ced4f86c4b866de1415cbc977ca7a7 /media
parentb492263fad2d811e7d942e63a61ce2f6a3fdfa7c (diff)
downloadchromium_src-ab34561dd992607626f7b7c7ee06d429de55df04.zip
chromium_src-ab34561dd992607626f7b7c7ee06d429de55df04.tar.gz
chromium_src-ab34561dd992607626f7b7c7ee06d429de55df04.tar.bz2
Detect errors in audio output and report them upstream.
Stop feeding audio packets to AUDIO DemuxerStreams once audio has been disabled. BUG=111409 TEST=uninstall pulseaudio, make /dev/snd inaccessible, and observe <video> plays correctly (muted) instead of hanging. Review URL: http://codereview.chromium.org/9234066 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119488 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/linux/alsa_output.cc2
-rw-r--r--media/audio/linux/alsa_output_unittest.cc10
-rw-r--r--media/base/audio_renderer_sink.h5
-rw-r--r--media/filters/ffmpeg_demuxer.cc12
-rw-r--r--media/filters/ffmpeg_demuxer.h4
5 files changed, 23 insertions, 10 deletions
diff --git a/media/audio/linux/alsa_output.cc b/media/audio/linux/alsa_output.cc
index b3f931d..75de924 100644
--- a/media/audio/linux/alsa_output.cc
+++ b/media/audio/linux/alsa_output.cc
@@ -268,6 +268,8 @@ bool AlsaPcmOutputStream::Open() {
// Finish initializing the stream if the device was opened successfully.
if (playback_handle_ == NULL) {
stop_stream_ = true;
+ TransitionTo(kInError);
+ return false;
} else {
bytes_per_output_frame_ = should_downmix_ ? 2 * bytes_per_sample_ :
bytes_per_frame_;
diff --git a/media/audio/linux/alsa_output_unittest.cc b/media/audio/linux/alsa_output_unittest.cc
index f1870d2..a8359f6 100644
--- a/media/audio/linux/alsa_output_unittest.cc
+++ b/media/audio/linux/alsa_output_unittest.cc
@@ -355,11 +355,10 @@ TEST_F(AlsaPcmOutputStreamTest, PcmOpenFailed) {
EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
.WillOnce(Return(kDummyMessage));
- ASSERT_TRUE(test_stream_->Open());
- ASSERT_EQ(AlsaPcmOutputStream::kIsOpened, test_stream_->state());
+ ASSERT_FALSE(test_stream_->Open());
+ ASSERT_EQ(AlsaPcmOutputStream::kInError, test_stream_->state());
// Ensure internal state is set for a no-op stream if PcmOpen() failes.
- EXPECT_EQ(AlsaPcmOutputStream::kIsOpened, test_stream_->state());
EXPECT_TRUE(test_stream_->stop_stream_);
EXPECT_TRUE(test_stream_->playback_handle_ == NULL);
EXPECT_FALSE(test_stream_->buffer_.get());
@@ -384,11 +383,10 @@ TEST_F(AlsaPcmOutputStreamTest, PcmSetParamsFailed) {
// If open fails, the stream stays in kCreated because it has effectively had
// no changes.
- ASSERT_TRUE(test_stream_->Open());
- EXPECT_EQ(AlsaPcmOutputStream::kIsOpened, test_stream_->state());
+ ASSERT_FALSE(test_stream_->Open());
+ EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream_->state());
// Ensure internal state is set for a no-op stream if PcmSetParams() failes.
- EXPECT_EQ(AlsaPcmOutputStream::kIsOpened, test_stream_->state());
EXPECT_TRUE(test_stream_->stop_stream_);
EXPECT_TRUE(test_stream_->playback_handle_ == NULL);
EXPECT_FALSE(test_stream_->buffer_.get());
diff --git a/media/base/audio_renderer_sink.h b/media/base/audio_renderer_sink.h
index 5888c6b..350210c 100644
--- a/media/base/audio_renderer_sink.h
+++ b/media/base/audio_renderer_sink.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -32,6 +32,9 @@ class AudioRendererSink
size_t number_of_frames,
size_t audio_delay_milliseconds) = 0;
+ // Signals an error has occurred.
+ virtual void OnError() = 0;
+
protected:
virtual ~RenderCallback() {}
};
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 6e3627e..0cb2ea4 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -289,7 +289,8 @@ FFmpegDemuxer::FFmpegDemuxer(MessageLoop* message_loop, bool local_source)
max_duration_(base::TimeDelta::FromMicroseconds(-1)),
deferred_status_(PIPELINE_OK),
first_seek_hack_(true),
- start_time_(kNoTimestamp()) {
+ start_time_(kNoTimestamp()),
+ audio_disabled_(false) {
DCHECK(message_loop_);
}
@@ -662,7 +663,9 @@ void FFmpegDemuxer::DemuxTask() {
// Defend against ffmpeg giving us a bad stream index.
if (packet->stream_index >= 0 &&
packet->stream_index < static_cast<int>(streams_.size()) &&
- streams_[packet->stream_index]) {
+ streams_[packet->stream_index] &&
+ (!audio_disabled_ ||
+ streams_[packet->stream_index]->type() != DemuxerStream::AUDIO)) {
FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index];
// If a packet is returned by FFmpeg's av_parser_parse2()
@@ -699,6 +702,7 @@ void FFmpegDemuxer::StopTask(const base::Closure& callback) {
void FFmpegDemuxer::DisableAudioStreamTask() {
DCHECK_EQ(MessageLoop::current(), message_loop_);
+ audio_disabled_ = true;
StreamVector::iterator iter;
for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
if (*iter && (*iter)->type() == DemuxerStream::AUDIO) {
@@ -722,8 +726,10 @@ void FFmpegDemuxer::StreamHasEnded() {
DCHECK_EQ(MessageLoop::current(), message_loop_);
StreamVector::iterator iter;
for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
- if (!*iter)
+ if (!*iter ||
+ (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) {
continue;
+ }
scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet(new AVPacket());
memset(packet.get(), 0, sizeof(*packet.get()));
(*iter)->EnqueuePacket(packet.Pass());
diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h
index 66c6ac5..a180113 100644
--- a/media/filters/ffmpeg_demuxer.h
+++ b/media/filters/ffmpeg_demuxer.h
@@ -261,6 +261,10 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer, public FFmpegURLProtocol {
// is 0.
base::TimeDelta start_time_;
+ // Whether audio has been disabled for this demuxer (in which case this class
+ // drops packets destined for AUDIO demuxer streams on the floor).
+ bool audio_disabled_;
+
DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxer);
};