| Index: media/filters/ffmpeg_demuxer.cc | 
| diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc | 
| index 249f97a0c731cb5a627696d2df6f1b886ae76a6a..872db84de830d5a4fad7b32108c483aeef4ddfe7 100644 | 
| --- a/media/filters/ffmpeg_demuxer.cc | 
| +++ b/media/filters/ffmpeg_demuxer.cc | 
| @@ -742,7 +742,7 @@ void FFmpegDemuxerStream::set_enabled(bool enabled, base::TimeDelta timestamp) { | 
| return; | 
| } | 
| if (!stream_status_change_cb_.is_null()) | 
| -    stream_status_change_cb_.Run(is_enabled_, timestamp); | 
| +    stream_status_change_cb_.Run(this, is_enabled_, timestamp); | 
| } | 
|  | 
| void FFmpegDemuxerStream::SetStreamStatusChangeCB( | 
| @@ -991,7 +991,8 @@ void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { | 
| // When seeking in an opus stream we need to ensure we deliver enough data to | 
| // satisfy the seek preroll; otherwise the audio at the actual seek time will | 
| // not be entirely accurate. | 
| -  FFmpegDemuxerStream* audio_stream = GetFFmpegStream(DemuxerStream::AUDIO); | 
| +  FFmpegDemuxerStream* audio_stream = | 
| +      GetFirstEnabledFFmpegStream(DemuxerStream::AUDIO); | 
| if (audio_stream) { | 
| const AudioDecoderConfig& config = audio_stream->audio_decoder_config(); | 
| if (config.codec() == kCodecOpus) | 
| @@ -1026,12 +1027,24 @@ base::Time FFmpegDemuxer::GetTimelineOffset() const { | 
| return timeline_offset_; | 
| } | 
|  | 
| -DemuxerStream* FFmpegDemuxer::GetStream(DemuxerStream::Type type) { | 
| +std::vector<DemuxerStream*> FFmpegDemuxer::GetStreams() { | 
| DCHECK(task_runner_->BelongsToCurrentThread()); | 
| -  return GetFFmpegStream(type); | 
| +  std::vector<DemuxerStream*> result; | 
| +  for (const auto& stream : streams_) { | 
| +    if (stream) | 
| +      result.push_back(stream.get()); | 
| +  } | 
| +  return result; | 
| } | 
|  | 
| -FFmpegDemuxerStream* FFmpegDemuxer::GetFFmpegStream( | 
| +void FFmpegDemuxer::SetStreamStatusChangeCB(const StreamStatusChangeCB& cb) { | 
| +  for (const auto& stream : streams_) { | 
| +    if (stream) | 
| +      stream->SetStreamStatusChangeCB(cb); | 
| +  } | 
| +} | 
| + | 
| +FFmpegDemuxerStream* FFmpegDemuxer::GetFirstEnabledFFmpegStream( | 
| DemuxerStream::Type type) const { | 
| for (const auto& stream : streams_) { | 
| if (stream && stream->type() == type && stream->enabled()) { | 
| @@ -1088,15 +1101,16 @@ void FFmpegDemuxer::NotifyCapacityAvailable() { | 
| void FFmpegDemuxer::NotifyBufferingChanged() { | 
| DCHECK(task_runner_->BelongsToCurrentThread()); | 
| Ranges<base::TimeDelta> buffered; | 
| -  FFmpegDemuxerStream* audio = GetFFmpegStream(DemuxerStream::AUDIO); | 
| -  FFmpegDemuxerStream* video = GetFFmpegStream(DemuxerStream::VIDEO); | 
| -  if (audio && video) { | 
| -    buffered = | 
| -        audio->GetBufferedRanges().IntersectionWith(video->GetBufferedRanges()); | 
| -  } else if (audio) { | 
| -    buffered = audio->GetBufferedRanges(); | 
| -  } else if (video) { | 
| -    buffered = video->GetBufferedRanges(); | 
| +  bool initialized_buffered_ranges = false; | 
| +  for (const auto& stream : streams_) { | 
| +    if (!stream) | 
| +      continue; | 
| +    if (initialized_buffered_ranges) { | 
| +      buffered = buffered.IntersectionWith(stream->GetBufferedRanges()); | 
| +    } else { | 
| +      buffered = stream->GetBufferedRanges(); | 
| +      initialized_buffered_ranges = true; | 
| +    } | 
| } | 
| host_->OnBufferedTimeRangesChanged(buffered); | 
| } | 
|  |