У меня есть медиа-поток с соответствующим именованным каналом. Программа считывает данные из каналов и обрабатывает кадры с помощью processFrame
.Haskell: Выполнение действия ввода-вывода только в том случае, если прошло определенное время с момента последнего его выполнения.
module Main where
import Codec.FFmpeg
import Codec.FFmpeg.Decode
import Control.Monad.Except (runExceptT)
main :: IO()
main = do
initFFmpeg
-- get IO reader
eResult <- runExceptT $ frameReader avPixFmtRgb24 (File "pipe")
case eResult of
Left err -> do print "couldn't establish frameReader\n"
print err
Right (getMaybeFrame, cleanup) -> do
-- read and process frames until av_read_frame returns no frames
loopWhileTrue (getAndProcessFrame getMaybeFrame)
cleanup
where
loopWhileTrue f = do result <- f
case result of
True -> loopWhileTrue f
False -> return()
where
getAndProcessFrame gMF = do
maybeFrame <- gMF
case maybeFrame of
Just frame -> do tc <- timeCondition
if tc
then do processFrame frame
else return()
return True
Nothing -> return False
timeCondition = return True
processFrame :: AVFrame -> IO()
processFrame frame = do isKeyFrame <- getKeyFrame frame
if isKeyFrame
then do pts <- getPts frame
print pts
else return()
мне нужно выполнить processFrame
только один раз в минуту, минуя все остальные кадры.
Этот код не имеет надлежащего времени, только timeCondition
заглушки. Я планировал написать правильную функцию timeCondition
, которая возвращает True
, когда определенное время прошло с последних processFrame
, в противном случае False
. Но это выглядит слишком настойчивым, и неясно, как использовать Monads/MVars для этого. Каков правильный способ разработки такой программы в Haskell?
Либо главное loopWhileTrue немного более сложным, отслеживание в последний раз кадр был обработан, или передать в MVar к getAndProcessFrame затем 'processFrame', который содержит в последний раз. Проверьте текущее время на этот последний раз на каждом кадре и условно продолжите или выйдите раньше. –
Наиболее очевидным улучшением структуры кода было бы сделать 'loopWhileTrue' связывание на верхнем уровне вместо того, чтобы закопать его в выражении' case' внутри блока 'do'. Кроме того, вы можете написать его 'loopWhileTrue f = do {result <- f; когда result $ loopWhileTrue f} ', или даже' loopWhileTrue f = fix $ \ m -> do {result <- f; когда результат m} '. Они будут давать сигнатуры типов 'loopWhileTrue :: Monad m => m Bool -> m()'. – dfeuer
Нет ли способа спать нить ни на минуту? (в 'loopWhileTrue') – Alec