La forma más fácil de abordar esto es usando variables y creo que el enfoque más fácil es agregar dos variables, una la cantidad de "arriba" y la otra la cantidad de "abajo" hasta cualquier fila. Una secuencia dada de subidas tiene un valor constante para el número de "bajadas" precedentes, y viceversa. Esta lógica se puede utilizar para la agregación.
La consulta resultante es:
select result, min(time_stamp) as start_time, max(time_stamp) as end_time
from (select r.*,
(@ups := @ups + (result = 'up')) as ups,
(@downs := @downs + (result = 'down')) as downs
from results r cross join
(select @ups := 0, @downs := 0) vars
where service_id = 1
order by time_stamp
) r
group by result, (case when result = 'up' then downs else ups end);