-- | Make a 'Stream' of media a segmented stream by using that has content which is an instance of 'CanSegment'. -- TODO move or merge - after deciding howto proceed with the package structure in general module Data.MediaBus.Conduit.Segment ( segmentC , segmentC' , forgetSegmentationC ) where import Conduit import Data.Monoid import Data.MediaBus.Basics.Series import Data.MediaBus.Basics.Ticks import Data.MediaBus.Media.Segment import Data.MediaBus.Media.Stream import Data.MediaBus.Conduit.Stream import Control.Lens import Data.Default import Data.Proxy import Control.Parallel.Strategies ( NFData ) -- | The packetizer recombines incoming packets into 'Segment's of the given -- size. The sequence numbers will be offsetted by the number extra frames -- generated. segmentC :: (Num s, Monad m, CanSegment c, Monoid c, Default i, CanBeTicks r t, HasDuration c, HasStaticDuration d) => Conduit (Stream i s (Ticks r t) p c) m (Stream i s (Ticks r t) p (Segment d c)) segmentC = segmentC' Proxy segmentC' :: (Num s, Monad m, CanSegment c, Monoid c, Default i, CanBeTicks r t, HasDuration c, HasStaticDuration d) => proxy d -> Conduit (Stream i s (Ticks r t) p c) m (Stream i s (Ticks r t) p (Segment d c)) segmentC' dpx = evalStateC (0, Nothing) $ awaitForever go where segmentDurationInTicks = nominalDiffTime # segmentDuration segmentDuration = getStaticDuration dpx go (MkStream (Next (MkFrame !t !s !cIn))) = do !cRest <- _2 <<.= Nothing let tsOffset = negate (getDurationTicks cRest) !cRest' <- yieldLoop (maybe cIn (<> cIn) cRest) tsOffset _2 .= cRest' where yieldLoop !c !timeOffset = if getDuration c == segmentDuration then do yieldWithAdaptedSeqNumAndTimestamp (MkSegment c) return Nothing else case splitAfterDuration dpx c of Just (!packet, !rest) -> do yieldWithAdaptedSeqNumAndTimestamp packet _1 += 1 yieldLoop rest (timeOffset + segmentDurationInTicks) Nothing -> do -- we just swallowed an incoming packet, therefore we need -- to decrease the seqnums _1 -= 1 return (Just c) where yieldWithAdaptedSeqNumAndTimestamp !p = do !seqNumOffset <- use _1 yieldNextFrame (MkFrame (t + timeOffset) (s + seqNumOffset) p) go (MkStream (Start !frmCtx)) = yieldStartFrameCtx frmCtx forgetSegmentationC :: (NFData c, Monad m) => Conduit (Stream i s t p (Segment d c)) m (Stream i s t p c) forgetSegmentationC = mapFrameContentC' _segmentContent