packages feed

mediabus 0.3.2.1 → 0.3.3.0

raw patch · 5 files changed

+142/−161 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.MediaBus.Media.Reframe: InputFrameIsEarly :: PushFrameError
- Data.MediaBus.Media.Reframe: InputFrameIsLate :: PushFrameError
- Data.MediaBus.Media.Reframe: InputFrameOverlaps :: PushFrameError
- Data.MediaBus.Media.Reframe: MkReframeError :: String -> Maybe d -> ReframerSt s d -> ReframeError s d
- Data.MediaBus.Media.Reframe: data PushFrameError
- Data.MediaBus.Media.Reframe: data ReframeError s d
- Data.MediaBus.Media.Reframe: data ReframerSt s d
- Data.MediaBus.Media.Reframe: generateFrame :: (Num s, Num d, Monad m, Eq d, Ord d, Show d) => d -> ReframerT m s d (Frame s d d)
- Data.MediaBus.Media.Reframe: initialReframerState :: (Num d, Num s) => ReframerSt s d
- Data.MediaBus.Media.Reframe: instance (GHC.Show.Show s, Data.Typeable.Internal.Typeable * s, GHC.Show.Show d, Data.Typeable.Internal.Typeable * d) => GHC.Exception.Exception (Data.MediaBus.Media.Reframe.ReframeError s d)
- Data.MediaBus.Media.Reframe: instance (GHC.Show.Show s, GHC.Show.Show d) => GHC.Show.Show (Data.MediaBus.Media.Reframe.ReframeError s d)
- Data.MediaBus.Media.Reframe: instance (GHC.Show.Show s, GHC.Show.Show d) => GHC.Show.Show (Data.MediaBus.Media.Reframe.ReframerSt s d)
- Data.MediaBus.Media.Reframe: instance GHC.Classes.Eq Data.MediaBus.Media.Reframe.PushFrameError
- Data.MediaBus.Media.Reframe: instance GHC.Classes.Ord Data.MediaBus.Media.Reframe.PushFrameError
- Data.MediaBus.Media.Reframe: instance GHC.Enum.Enum Data.MediaBus.Media.Reframe.PushFrameError
- Data.MediaBus.Media.Reframe: instance GHC.Show.Show Data.MediaBus.Media.Reframe.PushFrameError
- Data.MediaBus.Media.Reframe: mkReFrameError :: Monad m => String -> Maybe d -> ReframerT m s d (ReframeError s d)
- Data.MediaBus.Media.Reframe: nextFrameAvailableDuration :: (Num d, Monad m) => ReframerT m s d d
- Data.MediaBus.Media.Reframe: nextFrameTimestamp :: (Num d, Monad m) => ReframerT m s d d
- Data.MediaBus.Media.Reframe: pushFrame :: (Num d, Monad m, Eq d, Ord d) => Frame s d d -> ReframerT m s d (Maybe PushFrameError)
- Data.MediaBus.Media.Reframe: pushStartFrame :: (Num d, Monad m) => d -> ReframerT m s d ()
- Data.MediaBus.Media.Reframe: runReframer :: Monad m => ReframerT m s d a -> ReframerSt s d -> m (a, ReframerSt s d)
- Data.MediaBus.Media.Reframe: type ReframerT m s d a = StateT (ReframerSt s d) m a
+ Data.MediaBus.Media.SyncStream: assumeSynchronized :: Stream i s t p c -> SyncStream i p c
+ Data.MediaBus.Media.SyncStream: setSequenceNumbersAndTimestamps :: (Num s, CanBeTicks r t, HasDuration c) => SyncStream i p c -> (s, Ticks r t) -> (Stream i s (Ticks r t) p c, (s, Ticks r t))
+ Data.MediaBus.Media.SyncStream: type SyncStream i p c = Stream i () () p c
- Data.MediaBus.Basics.Series: _Next :: forall a_aqe6 b_aqe7 b_aqs9. Prism (Series a_aqe6 b_aqs9) (Series a_aqe6 b_aqe7) b_aqs9 b_aqe7
+ Data.MediaBus.Basics.Series: _Next :: forall a_aqaM b_aqaN b_aqoP. Prism (Series a_aqaM b_aqoP) (Series a_aqaM b_aqaN) b_aqoP b_aqaN
- Data.MediaBus.Basics.Series: _Start :: forall a_aqe6 b_aqe7 a_aqse. Prism (Series a_aqse b_aqe7) (Series a_aqe6 b_aqe7) a_aqse a_aqe6
+ Data.MediaBus.Basics.Series: _Start :: forall a_aqaM b_aqaN a_aqoU. Prism (Series a_aqoU b_aqaN) (Series a_aqaM b_aqaN) a_aqoU a_aqaM
- Data.MediaBus.Media.Discontinous: _Got :: forall a_aEhh a_aEJz. Prism (Discontinous a_aEJz) (Discontinous a_aEhh) a_aEJz a_aEhh
+ Data.MediaBus.Media.Discontinous: _Got :: forall a_aEdX a_aEGe. Prism (Discontinous a_aEGe) (Discontinous a_aEdX) a_aEGe a_aEdX
- Data.MediaBus.Media.Discontinous: _Missing :: forall a_aEhh. Prism' (Discontinous a_aEhh) ()
+ Data.MediaBus.Media.Discontinous: _Missing :: forall a_aEdX. Prism' (Discontinous a_aEdX) ()
- Data.MediaBus.Media.Stream: frameCtxInit :: forall i_aTbr s_aTbs t_aTbt p_aTbu p_aTl4. Lens (FrameCtx i_aTbr s_aTbs t_aTbt p_aTbu) (FrameCtx i_aTbr s_aTbs t_aTbt p_aTl4) p_aTbu p_aTl4
+ Data.MediaBus.Media.Stream: frameCtxInit :: forall i_aT86 s_aT87 t_aT88 p_aT89 p_aThJ. Lens (FrameCtx i_aT86 s_aT87 t_aT88 p_aT89) (FrameCtx i_aT86 s_aT87 t_aT88 p_aThJ) p_aT89 p_aThJ
- Data.MediaBus.Media.Stream: frameCtxSeqNumRef :: forall i_aTbr s_aTbs t_aTbt p_aTbu s_aTl5. Lens (FrameCtx i_aTbr s_aTbs t_aTbt p_aTbu) (FrameCtx i_aTbr s_aTl5 t_aTbt p_aTbu) s_aTbs s_aTl5
+ Data.MediaBus.Media.Stream: frameCtxSeqNumRef :: forall i_aT86 s_aT87 t_aT88 p_aT89 s_aThK. Lens (FrameCtx i_aT86 s_aT87 t_aT88 p_aT89) (FrameCtx i_aT86 s_aThK t_aT88 p_aT89) s_aT87 s_aThK
- Data.MediaBus.Media.Stream: frameCtxSourceId :: forall i_aTbr s_aTbs t_aTbt p_aTbu i_aTl6. Lens (FrameCtx i_aTbr s_aTbs t_aTbt p_aTbu) (FrameCtx i_aTl6 s_aTbs t_aTbt p_aTbu) i_aTbr i_aTl6
+ Data.MediaBus.Media.Stream: frameCtxSourceId :: forall i_aT86 s_aT87 t_aT88 p_aT89 i_aThL. Lens (FrameCtx i_aT86 s_aT87 t_aT88 p_aT89) (FrameCtx i_aThL s_aT87 t_aT88 p_aT89) i_aT86 i_aThL
- Data.MediaBus.Media.Stream: frameCtxTimestampRef :: forall i_aTbr s_aTbs t_aTbt p_aTbu t_aTl7. Lens (FrameCtx i_aTbr s_aTbs t_aTbt p_aTbu) (FrameCtx i_aTbr s_aTbs t_aTl7 p_aTbu) t_aTbt t_aTl7
+ Data.MediaBus.Media.Stream: frameCtxTimestampRef :: forall i_aT86 s_aT87 t_aT88 p_aT89 t_aThM. Lens (FrameCtx i_aT86 s_aT87 t_aT88 p_aT89) (FrameCtx i_aT86 s_aT87 t_aThM p_aT89) t_aT88 t_aThM
- Data.MediaBus.Media.Stream: framePayload :: forall s_aTlJ t_aTlK c_aTlL c_aTCm. Lens (Frame s_aTlJ t_aTlK c_aTlL) (Frame s_aTlJ t_aTlK c_aTCm) c_aTlL c_aTCm
+ Data.MediaBus.Media.Stream: framePayload :: forall s_aTio t_aTip c_aTiq c_aTz1. Lens (Frame s_aTio t_aTip c_aTiq) (Frame s_aTio t_aTip c_aTz1) c_aTiq c_aTz1
- Data.MediaBus.Media.Stream: frameSeqNum :: forall s_aTlJ t_aTlK c_aTlL s_aTCn. Lens (Frame s_aTlJ t_aTlK c_aTlL) (Frame s_aTCn t_aTlK c_aTlL) s_aTlJ s_aTCn
+ Data.MediaBus.Media.Stream: frameSeqNum :: forall s_aTio t_aTip c_aTiq s_aTz2. Lens (Frame s_aTio t_aTip c_aTiq) (Frame s_aTz2 t_aTip c_aTiq) s_aTio s_aTz2
- Data.MediaBus.Media.Stream: frameTimestamp :: forall s_aTlJ t_aTlK c_aTlL t_aTCo. Lens (Frame s_aTlJ t_aTlK c_aTlL) (Frame s_aTlJ t_aTCo c_aTlL) t_aTlK t_aTCo
+ Data.MediaBus.Media.Stream: frameTimestamp :: forall s_aTio t_aTip c_aTiq t_aTz3. Lens (Frame s_aTio t_aTip c_aTiq) (Frame s_aTio t_aTz3 c_aTiq) t_aTip t_aTz3
- Data.MediaBus.Media.Stream: stream :: forall i_aTCU s_aTCV t_aTCW p_aTCX c_aTCY i_aU2k s_aU2l t_aU2m p_aU2n c_aU2o. Iso (Stream i_aTCU s_aTCV t_aTCW p_aTCX c_aTCY) (Stream i_aU2k s_aU2l t_aU2m p_aU2n c_aU2o) (Streamish i_aTCU s_aTCV t_aTCW p_aTCX c_aTCY) (Streamish i_aU2k s_aU2l t_aU2m p_aU2n c_aU2o)
+ Data.MediaBus.Media.Stream: stream :: forall i_aTzz s_aTzA t_aTzB p_aTzC c_aTzD i_aTYZ s_aTZ0 t_aTZ1 p_aTZ2 c_aTZ3. Iso (Stream i_aTzz s_aTzA t_aTzB p_aTzC c_aTzD) (Stream i_aTYZ s_aTZ0 t_aTZ1 p_aTZ2 c_aTZ3) (Streamish i_aTzz s_aTzA t_aTzB p_aTzC c_aTzD) (Streamish i_aTYZ s_aTZ0 t_aTZ1 p_aTZ2 c_aTZ3)

Files

mediabus.cabal view
@@ -1,5 +1,5 @@ name: mediabus-version: 0.3.2.1+version: 0.3.3.0 cabal-version: >=1.10 build-type: Simple license: BSD3@@ -52,10 +52,10 @@         Data.MediaBus.Media.Channels         Data.MediaBus.Media.Discontinous         Data.MediaBus.Media.Media-        Data.MediaBus.Media.Reframe         Data.MediaBus.Media.Samples         Data.MediaBus.Media.Segment         Data.MediaBus.Media.Stream+        Data.MediaBus.Media.SyncStream         Data.MediaBus.Transport.Udp     build-depends:         QuickCheck <2.10,@@ -150,6 +150,7 @@     other-modules:         Data.MediaBus.Conduit.Audio.Raw.ResampleSpec         Data.MediaBus.Media.BufferSpec+        Data.MediaBus.Media.SyncStreamSpec         Data.MediaBus.Conduit.SegmentSpec         Data.MediaBus.Conduit.ReorderSpec         Data.MediaBus.Conduit.StreamSpec
+ specs/Data/MediaBus/Media/SyncStreamSpec.hs view
@@ -0,0 +1,94 @@+module Data.MediaBus.Media.SyncStreamSpec+  ( spec+  ) where++import Control.Lens+import Control.Monad.State+import Data.Function+import Data.MediaBus+import Debug.Trace+import Test.Hspec+import Test.QuickCheck++newtype FakePayload = FP+  { fakeDuration :: Ticks64At8000+  } deriving (Eq, Show, Num, Arbitrary, Ord)++instance HasDuration FakePayload where+  getDuration = view (to fakeDuration . nominalDiffTime)++spec :: Spec+spec =+  describe "setSequenceNumbersAndTimestamps" $ do+    it "increases the sequence number by one (only) for each frame" $+      let prop :: (NonEmptyList (SyncStream () () FakePayload)) -> Bool+          prop (NonEmpty inStr) =+            let expectedLastSeqNum =+                  let isNext (MkStream (Next _)) = True+                      isNext _ = False+                  in max 0 (fromIntegral (length (filter isNext inStr)) - 1)+                actualLastSeqNum =+                  let outStr =+                        let z :: (SeqNum16, Ticks64At8000)+                            z = (0, 0)+                        in evalState+                             (mapM+                                (state . setSequenceNumbersAndTimestamps)+                                inStr)+                             z+                  in case last outStr of+                       MkStream (Next f) -> f ^. seqNum+                       MkStream (Start f) -> max 0 (f ^. seqNum - 1)+            in expectedLastSeqNum == actualLastSeqNum+      in property prop+    it "increases the sequence number monotonic" $+      let prop :: (NonEmptyList (SyncStream () () FakePayload)) -> Bool+          prop (NonEmpty inStr) =+            let seqNumDiffs =+                  let outFrames =+                        let isNext (MkStream (Next _)) = True+                            isNext _ = False+                            outStr =+                              let z :: (SeqNum16, Ticks64At8000)+                                  z = (0, 0)+                              in evalState+                                   (mapM+                                      (state . setSequenceNumbersAndTimestamps)+                                      inStr)+                                   z+                        in filter isNext outStr+                  in zipWith ((-) `on` (view seqNum)) (drop 1 outFrames) outFrames+            in all (== 1) seqNumDiffs+      in property prop+    it "increases the timestamps by the duration of each frame" $+      let prop :: (NonEmptyList (SyncStream () () FakePayload)) -> Bool+          prop (NonEmpty inStr) =+            let isNext (MkStream (Next _)) = True+                isNext _ = False+                outFrames :: [Stream () SeqNum16 Ticks64At8000 () FakePayload]+                outFrames =+                  let outStr =+                        let z :: (SeqNum16, Ticks64At8000)+                            z = (0, MkTicks 0)+                        in evalState+                             (mapM+                                (state . setSequenceNumbersAndTimestamps)+                                inStr)+                             z+                  in filter isNext outStr+                timestamps = map (view timestamp) outFrames+                expectedTimestamps :: [Ticks64At8000]+                expectedTimestamps =+                  let inFramesWithoutLast =+                        (filter isNext inStr)+                      inDurations =+                        map (view (from nominalDiffTime) . getDuration)+                        inFramesWithoutLast++                  in scanl (+) 0 inDurations+            in if and (zipWith (==) timestamps expectedTimestamps)+                 then True+                 else traceShow ( timestamps+                                , expectedTimestamps+                                , outFrames) False+      in property prop
src/Data/MediaBus.hs view
@@ -36,8 +36,8 @@ import Data.MediaBus.Media.Channels as X import Data.MediaBus.Media.Discontinous as X import Data.MediaBus.Media.Media as X-import Data.MediaBus.Media.Reframe as X import Data.MediaBus.Media.Samples as X import Data.MediaBus.Media.Segment as X import Data.MediaBus.Media.Stream as X+import Data.MediaBus.Media.SyncStream as X import Data.MediaBus.Transport.Udp as X
− src/Data/MediaBus/Media/Reframe.hs
@@ -1,158 +0,0 @@--- | This module contains functions and types for reframing the sequence number---   and timestamps of 'Frame's.------   This means that this module will allow you to record a set of incoming---   frames using 'pushFrame'. Whenever you want to extract the timing and---   sequence number information of the next frame with a given duration,---   use 'generateFrame'.-module Data.MediaBus.Media.Reframe-  ( initialReframerState-  , runReframer-  , pushStartFrame-  , pushFrame-  , PushFrameError(..)-  , nextFrameAvailableDuration-  , nextFrameTimestamp-  , generateFrame-  , type ReframerT-  , ReframerSt()-  , ReframeError(..)-  , mkReFrameError-  ) where--import Control.Exception-import Control.Monad-import Control.Monad.Trans.State.Strict as State-import Data.MediaBus.Media.Stream-import Data.Typeable---- | Create an empty initial state.-initialReframerState-  :: (Num d, Num s)-  => ReframerSt s d-initialReframerState = MkTimeFrame 0 0 0---- | Run state 'ReframerSt' state transformer.-runReframer-  :: Monad m-  => ReframerT m s d a -> ReframerSt s d -> m (a, ReframerSt s d)-runReframer = runStateT---- | Reset the current timing and sequence number, and start with the given---   start time.-pushStartFrame-  :: (Num d, Monad m)-  => d -> ReframerT m s d ()-pushStartFrame d = do-  (MkTimeFrame _ s _) <- State.get-  State.put (MkTimeFrame d s d)---- | Increase the available duration by the duration in the frame,  iff the---   timestamp of the given frame matches exactly the timestamp after the end---   of the available period, otherwise do nothing with the state and return---   'True'.-pushFrame-  :: (Num d, Monad m, Eq d, Ord d)-  => Frame s d d -> ReframerT m s d (Maybe PushFrameError)-pushFrame (MkFrame ts _ dur) = do-  (MkTimeFrame startTs nextSeq endTs) <- State.get-  let endTs' = ts + dur-  when (ts == endTs) (State.put (MkTimeFrame startTs nextSeq endTs'))-  return-    (if | ts < endTs && endTs' < endTs -> Just InputFrameIsLate-        | ts < endTs && endTs' >= endTs -> Just InputFrameOverlaps-        | ts > endTs -> Just InputFrameIsEarly-        | ts == endTs -> Nothing)---- | Specifies in what way 'pushFrame' failed-data PushFrameError-  = InputFrameIsLate -- ^ The input frame ends before '_endTs'-  | InputFrameOverlaps -- ^ The input frame starts before, and ends after '_endTs'-  | InputFrameIsEarly -- ^ The input frame begins after '_endTs'-  deriving (Eq, Ord, Show, Enum)---- | Return the duration of the frames recorded with 'pushFrame'.-nextFrameAvailableDuration-  :: (Num d, Monad m)-  => ReframerT m s d d-nextFrameAvailableDuration = do-  (MkTimeFrame startTs _ endTs) <- State.get-  return (endTs - startTs)---- | Return the timestamp of the frame being build. .-nextFrameTimestamp-  :: (Num d, Monad m)-  => ReframerT m s d d-nextFrameTimestamp = do-  (MkTimeFrame startTs _ _) <- State.get-  return startTs---- | Try to create a frame with the given duration, and update the state---   accordingly, the actual duration, that was available is---   put into the payload field of the frame returned.---   The start time stamp of the next frame---   is always incremented by the @wantedDureation@ regardless of wether it was---   available.-generateFrame-  :: (Num s, Num d, Monad m, Eq d, Ord d, Show d)-  => d -> ReframerT m s d (Frame s d d)-generateFrame wantedDuration = do-  (MkTimeFrame startTs nextSeq endTs) <- State.get-  available <- nextFrameAvailableDuration-  let endTs' = max (startTs + wantedDuration) endTs-  State.put (MkTimeFrame (startTs + wantedDuration) (nextSeq + 1) endTs')-  return (MkFrame startTs nextSeq (wantedDuration `min` available))---- | Reframer state.-data ReframerSt s d = MkTimeFrame-  { _startTs :: !d-  , _nextSeqNum :: !s-  , _endTs :: !d-  } deriving (Typeable)--instance (Show s, Show d) =>-         Show (ReframerSt s d) where-  showsPrec d MkTimeFrame {_startTs, _nextSeqNum, _endTs} =-    showParen-      (d > 10)-      (showString "reframer-state: " .-       showString "start: " .-       showsPrec 11 _startTs .-       showString ", end: " .-       showsPrec 11 _endTs . showString ", next-sn: " . showsPrec 11 _nextSeqNum)---- | The 'ReframerSt' 'StateT' transformer-type ReframerT m s d a = StateT (ReframerSt s d) m a---- | The exception type for 'encodeLinearToAacC'-data ReframeError s d = MkReframeError-  { reframeError :: String-  , reframeErrorRequestedOutput :: Maybe d-  , reframeErrorSt :: ReframerSt s d-  } deriving (Typeable)--instance (Show s, Show d) =>-         Show (ReframeError s d) where-  showsPrec d MkReframeError { reframeError-                             , reframeErrorRequestedOutput-                             , reframeErrorSt-                             } =-    showParen-      (d > 10)-      (showString "reframe-error: " .-       showsPrec 11 reframeError .-       maybe-         id-         (\ro -> showString ", requested: " . showsPrec 11 ro)-         reframeErrorRequestedOutput .-       showString ", " . showsPrec 11 reframeErrorSt)--instance (Show s, Typeable s, Show d, Typeable d) =>-         Exception (ReframeError s d)---- | Utility function to generate a 'ReframeError' with the current state.-mkReFrameError-  :: Monad m-  => String -> Maybe d -> ReframerT m s d (ReframeError s d)-mkReFrameError msg requestedOutputDuration =-  MkReframeError msg requestedOutputDuration <$> State.get
+ src/Data/MediaBus/Media/SyncStream.hs view
@@ -0,0 +1,44 @@+-- | Naturally ordered 'Stream's.+-- A 'Stream' without sequence numbers and timestamps has no means to represent+-- 'Frame's that have varying sequence numbers or timestamps, hence they cannot+-- be part of a stream that is not perfectly synchronized, therefore when consuming+-- such 'Stream' values, the corresponding callers must work under the assumption+-- that the frames are perfectly synchronous.+module Data.MediaBus.Media.SyncStream+  ( type SyncStream+  , assumeSynchronized+  , setSequenceNumbersAndTimestamps+  ) where++import Data.MediaBus.Basics.Series+import Data.MediaBus.Basics.Ticks+import Data.MediaBus.Media.Stream++-- | A 'Stream' without a meaningful sequence number or timestamp.+type SyncStream i p c = Stream i () () p c++-- | Convert a 'Stream' to a 'SyncStream' by simply /forgetting/ the sequence+-- numbers and timestamps of the input. This expresses the assumption that the+-- 'Frame's are either perfectly lined sequential or that this doesn't matter+-- at all.+assumeSynchronized :: Stream i s t p c -> SyncStream i p c+assumeSynchronized (MkStream (Start (MkFrameCtx i _ _ p))) =+  MkStream (Start (MkFrameCtx i () () p))+assumeSynchronized (MkStream (Next (MkFrame _ _ c))) =+  MkStream (Next (MkFrame () () c))++-- | Set sequence numbers and timestamps.+-- Increment the sequence numbers starting from @0@ for every frame.+-- Start the timestamp at @0@ and add the 'Frame' duration of the 'Next'+-- frame in the stream.+-- This function has the signature required to turn it into a 'State' monad.+setSequenceNumbersAndTimestamps+  :: (Num s, CanBeTicks r t, HasDuration c)+  => SyncStream i p c+  -> (s, Ticks r t)+  -> (Stream i s (Ticks r t) p c, (s, Ticks r t))+setSequenceNumbersAndTimestamps (MkStream (Next (MkFrame _t _s !c))) (nextS, nextT) =+  ( MkStream (Next (MkFrame nextT nextS c))+  , (nextS + 1, nextT + getDurationTicks c))+setSequenceNumbersAndTimestamps (MkStream (Start (MkFrameCtx i _t _s p))) (nextS, nextT) =+  ((MkStream (Start (MkFrameCtx i nextT nextS p))), (nextS, nextT))