isobmff-builder (empty) → 0.1.0.0
raw patch · 10 files changed
+637/−0 lines, 10 filesdep +basedep +bytestringdep +type-listsetup-changed
Dependencies added: base, bytestring, type-list
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- isobmff-builder.cabal +57/−0
- src/Data/ByteString/IsoBaseFileFormat/Boxes/Box.hs +407/−0
- src/Data/ByteString/IsoBaseFileFormat/Boxes/FileType.hs +24/−0
- src/Data/ByteString/IsoBaseFileFormat/Boxes/MediaData.hs +21/−0
- src/Data/ByteString/IsoBaseFileFormat/Boxes/MovieBox.hs +39/−0
- src/Data/ByteString/IsoBaseFileFormat/Boxes/ProgressiveDownloadInformation.hs +25/−0
- src/Data/ByteString/IsoBaseFileFormat/Boxes/Skip.hs +21/−0
- src/Data/ByteString/IsoBaseFileFormat/Builder.hs +11/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Sven Heyll (c) 2016++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Author name here nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ isobmff-builder.cabal view
@@ -0,0 +1,57 @@+name: isobmff-builder+version: 0.1.0.0+synopsis: A (bytestring-) builder for the ISO base media file format ISO-14496-12+description: Please see README.md+homepage: https://github.com/sheyll/isobmff-builder#readme+license: BSD3+license-file: LICENSE+author: Sven Heyll+maintainer: sven.heyll@gmail.com+copyright: 2016 Sven Heyll+category: Codec+build-type: Simple+-- extra-source-files:+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: Data.ByteString.IsoBaseFileFormat.Builder+ , Data.ByteString.IsoBaseFileFormat.Boxes.Box+ , Data.ByteString.IsoBaseFileFormat.Boxes.FileType+ , Data.ByteString.IsoBaseFileFormat.Boxes.MediaData+ , Data.ByteString.IsoBaseFileFormat.Boxes.Skip+ , Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation+ , Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox+ build-depends: base >= 4.7 && < 5+ , bytestring >= 0.10.8.1+ , type-list >= 0.5.0.0+ default-language: Haskell2010+ default-extensions: ConstraintKinds+ , CPP+ , DataKinds+ , DefaultSignatures+ , DeriveDataTypeable+ , DeriveFunctor+ , DeriveGeneric+ , FlexibleInstances+ , FlexibleContexts+ , FunctionalDependencies+ , GADTs+ , GeneralizedNewtypeDeriving+ , KindSignatures+ , MultiParamTypeClasses+ , OverloadedStrings+ , QuasiQuotes+ , RecordWildCards+ , RankNTypes+ , ScopedTypeVariables+ , StandaloneDeriving+ , TemplateHaskell+ , TupleSections+ , TypeFamilies+ , TypeInType+ , TypeOperators+ , TypeSynonymInstances+source-repository head+ type: git+ location: https://github.com/githubuser/isobmff-builder
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/Box.hs view
@@ -0,0 +1,407 @@+{-# LANGUAGE UndecidableInstances #-}++-- | Definition of the most basic elements in an ISOBMFF file /boxes/.+-- See Chapter 4 in the standard document. Since the standard+module Data.ByteString.IsoBaseFileFormat.Boxes.Box+ (module Data.ByteString.IsoBaseFileFormat.Boxes.Box, module X)+ where++import Data.Bits as X+import Data.ByteString.Builder as X+import Data.Monoid as X+import Data.Proxy as X+import Data.Word as X+import GHC.TypeLits as X+import Data.String+import Data.Type.Equality++import Data.Type.List+import Data.Type.Bool+import Data.Type.Equality+import GHC.Exts++-- * Type-safe box composition++-- | A box that may contain nested boxes. The nested boxes are type checked to+-- be valid in the container box. This results in a container-box with only+-- valid and all required child boxes. This is checked by the type system.+boxes :: forall ts t.+ (IsBoxType t,ValidBoxes t ts)+ => Boxes t ts -> Box t+boxes = box++-- | A container-box with child boxes.+data Boxes (cont :: x) (boxTypes :: [x]) where+ Parent :: IsBoxType t => Box t -> Boxes t '[]+ (:-) :: IsBoxType t => Boxes c ts -> Box t -> Boxes c (t ': ts)++infixl 2 :-++-- | A container box that contains only the parent, and no children (yet).+type Container parent = Boxes parent '[]++-- | An operator for @Parent parent :- firstChild@+(^-) :: (IsBoxType t, IsBoxType u) => Box t -> Box u -> Boxes t '[u]+parent ^- firstChild = Parent parent :- firstChild++infixl 2 ^-++-- | To be nested into a box, 'Boxes' must be an instance of 'IsBoxContent'.+-- This instance concatenates all nested boxes.+instance (IsBoxType t,ValidBoxes t bs) => IsBoxContent (Boxes t bs) where+ boxSize bs = boxSize (UnverifiedBoxes bs)+ boxBuilder bs = boxBuilder (UnverifiedBoxes bs)++-- | An internal wrapper type around 'Boxes' for the 'IsBoxContent' instance.+-- Since the 'IsBoxContent' instance recursivly deconstructs a 'Boxes' the+-- constraints for the validity 'ValidBoxes' cannot be asserted. To circumvent+-- this the 'IsBoxContent' instance for 'Boxes' delegates to the instance of+-- 'UnverifiedBoxes', which has no 'ValidBoxes' constraint in the instance head.+newtype UnverifiedBoxes t ts = UnverifiedBoxes (Boxes t ts)++instance IsBoxContent (UnverifiedBoxes t bs) where+ boxSize (UnverifiedBoxes (Parent c)) = boxSize c+ boxSize (UnverifiedBoxes (bs :- b)) = boxSize (UnverifiedBoxes bs) + boxSize b+ boxBuilder (UnverifiedBoxes (Parent c)) = boxBuilder c+ boxBuilder (UnverifiedBoxes (bs :- b)) = boxBuilder (UnverifiedBoxes bs) <> boxBuilder b++-- * Type level consistency checks++-- | A type-level check that uses 'BoxRules' to check that the contained boxes+-- are standard conform.+type ValidBoxes t ts =+ ( AllAllowedIn t ts ~ 'True+ , HasAllRequiredBoxes t (RequiredNestedBoxes t) ts ~ 'True+ , CheckTopLevelOk t ~ 'True)++-- | A type function to check that all nested boxes are allowed in the+-- container.+type family AllAllowedIn (container :: k) (boxes :: [k]) :: Bool+ where+ AllAllowedIn c '[] = 'True+ AllAllowedIn c (t ': ts) =+ If (CheckAllowedIn c t (RestrictedTo t))+ (AllAllowedIn c ts)+ (TypeError (NotAllowedMsg c t))++type family CheckAllowedIn (c :: k) (t :: k) (a :: Maybe [k]) :: Bool where+ CheckAllowedIn c t 'Nothing = 'True+ CheckAllowedIn c t ('Just rs) = Find c rs+++-- | The custom (type-) error message for 'AllAllowedIn'.+type NotAllowedMsg c t =+ Text "Boxes of type: "+ :<>: ShowType c+ :<>: Text " may not contain boxes of type "+ :<>: ShowType t+ :$$: Text "Valid containers for "+ :<>: ShowType t+ :<>: Text " boxes are: "+ :$$: ShowType (RestrictedTo t)+ :$$: ShowType t+ :<>: If (IsTopLevelBox c)+ (Text " boxes may appear top-level in a file.")+ (Text " boxes must be nested.")+++-- | Check that all required boxes have been nested.+type family HasAllRequiredBoxes (c :: k) (req :: [k]) (nested :: [k]) :: Bool+ where+ HasAllRequiredBoxes c '[] nested = 'True+ HasAllRequiredBoxes c (r ': restReq) nested =+ If (Find r nested)+ (HasAllRequiredBoxes c restReq nested)+ (TypeError (MissingRequired c r nested))++type IsSubSet base sub = Intersection base sub == sub++-- | The custom (type-) error message for 'HasAllRequiredBoxes'.+type MissingRequired c r nested =+ Text "Boxes of type: "+ :<>: ShowType c+ :<>: Text " require these nested boxes: "+ :<>: ShowType (RequiredNestedBoxes c)+ :$$: Text "but only these box types were nested: "+ :<>: ShowType nested+ :$$: Text "e.g. this type is missing: "+ :<>: ShowType r++-- | Check that the box may appear top-level.+type family CheckTopLevelOk (t :: k) :: Bool where+ CheckTopLevelOk t = IsTopLevelBox t || TypeError (NotTopLevenError t)++-- | The custom (type-) error message indicating that a box may not appear+-- top-level.+type NotTopLevenError c =+ Text "Boxes of type "+ :<>: ShowType c+ :<>: Text " MUST be nested inside boxes of these types: "+ :$$: ShowType (RestrictedTo c)++-- * Common box /combinators/++-- | A `Box` with /version/ and /branding/ information+type FullBox t = Extend FullBoxHeader t++-- | Create a 'FullBox' from a 'FourCc' 'StdType' and the nested box content.+fullBox+ :: (IsBoxType t, IsBoxContent c)+ => BoxVersion -> BoxFlags 24 -> c -> Box t+fullBox ver fs cnt = box (Extend (FullBoxHeader ver fs) cnt)++-- | The additional header with /version/ and /branding/ information+data FullBoxHeader =+ FullBoxHeader BoxVersion+ (BoxFlags 24)++instance IsBoxContent FullBoxHeader where+ boxSize (FullBoxHeader _ f) = 1 + boxSize f+ boxBuilder (FullBoxHeader (BoxVersion v) f) = word8 v <> boxBuilder f++-- | The box version (in a 'FullBox') is a single byte+newtype BoxVersion =+ BoxVersion Word8++-- | In addition to a 'BoxVersion' there can be 24 bits for custom flags etc in+-- a 'FullBox'.+newtype BoxFlags bits =+ BoxFlags Integer+ deriving (Eq,Show,Num)++-- | Internal function that creates a bit mask with all bits in a 'BoxFlags' set+-- to 1.+boxFlagBitMask :: KnownNat bits+ => BoxFlags bits -> Integer+boxFlagBitMask px = 2 ^ natVal px - 1++-- | Internal function that masks-out all bits higher than 'bits'.+cropBits :: KnownNat bits+ => BoxFlags bits -> BoxFlags bits+cropBits f@(BoxFlags b) = BoxFlags (b .&. boxFlagBitMask f)++-- | Get the number of bytes required to store a number of bits.+instance KnownNat bits => IsBoxContent (BoxFlags bits) where+ boxSize f =+ let minBytes = fromInteger $ natVal f `div` 8+ modBytes = fromInteger $ natVal f `mod` 8+ in BoxSize $ minBytes + signum modBytes+ boxBuilder f@(BoxFlags b) =+ let bytes =+ let (BoxSize bytes') = boxSize f+ in fromIntegral bytes'+ wordSeq n+ | n <= bytes =+ word8 (fromIntegral (shiftR b ((bytes - n) * 8) .&. 255)) <>+ wordSeq (n + 1)+ | otherwise = mempty+ in wordSeq 1++instance KnownNat bits => Bits (BoxFlags bits) where+ (.&.) lf@(BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ l .&. r+ (.|.) lf@(BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ l .&. r+ xor (BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ xor l r+ complement (BoxFlags x) = cropBits $ BoxFlags $ complement x+ shift (BoxFlags x) = cropBits . BoxFlags . shift x+ rotateL = error "TODO rotateL"+ rotateR = error "TODO rotateR"+ bitSize = fromInteger . natVal+ bitSizeMaybe = Just . fromInteger . natVal+ isSigned _ = False+ testBit f n =+ let (BoxFlags b) = cropBits f+ in testBit b n+ bit = cropBits . BoxFlags . bit+ popCount f =+ let (BoxFlags b) = cropBits f+ in popCount b+ zeroBits = BoxFlags 0++-- * /The/ actual Box++-- | Create a 'Box' with a 'StdType' 'FourCc' type.+box :: forall t c.+ (IsBoxType t,IsBoxContent c)+ => c -> Box t+box cnt = Box (toBoxType (Proxy :: Proxy t)) cnt++-- | An /empty/ box. This is for boxes without fields. All these boxes contain+-- is their obligatory 'BoxHeader' possibly nested boxes.+emptyBox :: forall t . (IsBoxType t) => Box t+emptyBox = box ()++-- | A type that wraps the contents of a box and the box type.+data Box (b :: t) where+ Box :: (IsBoxType t,IsBoxContent c) => BoxType -> c -> Box t++instance IsBoxContent (Box t) where+ boxBuilder b@(Box t cnt) = sFix <> tFix <> sExt <> tExt <> boxBuilder cnt+ where s = boxSize b+ sFix = boxBuilder s+ sExt = boxBuilder (BoxSizeExtension s)+ tFix = boxBuilder t+ tExt = boxBuilder (BoxTypeExtension t)+ boxSize b@(Box t cnt) = sPayload + boxSize (BoxSizeExtension sPayload)+ where sPayload =+ boxSize sPayload + boxSize t + boxSize cnt ++ boxSize (BoxTypeExtension t)++-- * Box Meta Data+-- | The box header contains a size and a type. Both can be compact (32bit) or+-- large (64bit size, 17*32bit type).+data BoxHeader =+ BoxHeader BoxSize+ BoxType+ deriving (Show,Eq)++-- | The size of the box. If the size is limited to a (fixed) value, it can be+-- provided as a 'Word64' which will be represented as either a 32bit compact+-- size or as 64 bit /largesize/. If 'UnlimitedSize' is used, the box extends to+-- the end of the file.+data BoxSize+ = UnlimitedSize+ | BoxSize Word64+ deriving (Show,Eq)++instance IsBoxContent BoxSize where+ boxSize _ = BoxSize 4+ boxBuilder UnlimitedSize = word32BE 0+ boxBuilder (BoxSize n) =+ word32BE $+ if n < 2 ^ 32+ then fromIntegral n+ else 1++instance Num BoxSize where+ (+) UnlimitedSize _ = UnlimitedSize+ (+) _ UnlimitedSize = UnlimitedSize+ (+) (BoxSize l) (BoxSize r) = BoxSize (l + r)+ (-) UnlimitedSize _ = UnlimitedSize+ (-) _ UnlimitedSize = UnlimitedSize+ (-) (BoxSize l) (BoxSize r) = BoxSize (l - r)+ (*) UnlimitedSize _ = UnlimitedSize+ (*) _ UnlimitedSize = UnlimitedSize+ (*) (BoxSize l) (BoxSize r) = BoxSize (l * r)+ abs UnlimitedSize = UnlimitedSize+ abs (BoxSize n) = BoxSize (abs n)+ signum UnlimitedSize = UnlimitedSize+ signum (BoxSize n) = BoxSize (signum n)+ fromInteger n = BoxSize $ fromInteger n++-- | The 'BoxSize' can be > 2^32 in which case an 'BoxSizeExtension' must be+-- added after the type field.+data BoxSizeExtension =+ BoxSizeExtension BoxSize++instance IsBoxContent BoxSizeExtension where+ boxBuilder (BoxSizeExtension UnlimitedSize) = mempty+ boxBuilder (BoxSizeExtension (BoxSize n)) =+ if n < 2 ^ 32+ then mempty+ else word64BE n+ boxSize (BoxSizeExtension UnlimitedSize) = 0+ boxSize (BoxSizeExtension (BoxSize n)) =+ BoxSize $+ if n < 2 ^ 32+ then 0+ else 8++-- | A box has a /type/, this is the value level representation for the box type.+data BoxType+ =+ -- | `FourCc` can be used as @boxType@ in `Box`, standard four letter character+ -- code, e.g. @ftyp@+ StdType FourCc+ |+ -- | CustomBoxType defines custom @boxType@s in `Box`es.+ CustomBoxType String+ deriving (Show,Eq)++-- | Convert type level box types to values+class BoxRules t => IsBoxType (t :: k) where+ toBoxType :: proxy t -> BoxType++instance (BoxRules t, KnownSymbol t) => IsBoxType t where+ toBoxType _ = StdType (fromString (symbolVal (Proxy :: Proxy t)))++-- | A class that describes (on the type level) how a box can be nested into+-- other boxes (see 'Boxes').+class BoxRules (t :: k) where+ -- | List of boxes that this box can be nested into.+ type RestrictedTo t :: Maybe [k]+ type RestrictedTo t = 'Just '[]+ -- | If the box is also allowed 'top-level' i.e. in the file directly, not+ -- nested in an other box.+ type IsTopLevelBox t :: Bool+ type IsTopLevelBox t = 'True+ -- | Describes which nested boxes MUST be present in a box using 'boxes'.+ type RequiredNestedBoxes t :: [k]+ type RequiredNestedBoxes t = '[]+ -- | Describes how many times a box should be present in a container (-box).+ type GetCardinality t (c :: k) :: Cardinality+ type GetCardinality t any = ExactlyOnce++-- | Describes how many times a box should be present in a container.+data Cardinality = AtMostOnce | ExactlyOnce | OnceOrMore++-- | A type containin a printable four letter character code.+newtype FourCc =+ FourCc (Char,Char,Char,Char)+ deriving (Show,Eq)++instance IsString FourCc where+ fromString str+ | length str == 4 =+ let [a,b,c,d] = str+ in FourCc (a,b,c,d)+ | otherwise =+ error ("cannot make a 'FourCc' of a String which isn't exactly 4 bytes long: " +++ show str ++ " has a length of " ++ show (length str))++instance IsBoxContent FourCc where+ boxSize _ = 4+ boxBuilder (FourCc (a,b,c,d)) = putW a <> putW b <> putW c <> putW d+ where putW = word8 . fromIntegral . fromEnum++instance IsBoxContent BoxType where+ boxSize _ = boxSize (FourCc undefined)+ boxBuilder t =+ case t of+ StdType x -> boxBuilder x+ CustomBoxType u -> boxBuilder (FourCc ('u','u','i','d'))++-- | When using custom types extra data must be written after the extra size+-- information. Since the box type and the optional custom box type are not+-- guaranteed to be consequtive, this type handles the /second/ part seperately.+data BoxTypeExtension =+ BoxTypeExtension BoxType++instance IsBoxContent BoxTypeExtension where+ boxSize (BoxTypeExtension (StdType _)) = 0+ boxSize (BoxTypeExtension (CustomBoxType _)) = 16 * 4+ boxBuilder (BoxTypeExtension (StdType _)) = mempty+ boxBuilder (BoxTypeExtension (CustomBoxType str)) =+ mconcat (map (word8 . fromIntegral . fromEnum)+ (take (16 * 4) str) +++ repeat (word8 0))++-- | Box content composed of box contents @a@ and @b@.+data Extend a b =+ Extend a+ b++instance (IsBoxContent p,IsBoxContent c) => IsBoxContent (Extend p c) where+ boxSize (Extend p c) = boxSize p + boxSize c+ boxBuilder (Extend p c) = boxBuilder p <> boxBuilder c++-- | Types that go into a box. A box content is a piece of data that can be+-- reused in different instances of 'IsBox'. It has no 'BoxType' and hence+-- defines no box.+class IsBoxContent a where+ boxSize :: a -> BoxSize+ boxBuilder :: a -> Builder++-- | An empty box content can by represented by @()@ (i.e. /unit/).+instance IsBoxContent () where+ boxSize _ = 0+ boxBuilder _ = mempty
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/FileType.hs view
@@ -0,0 +1,24 @@+module Data.ByteString.IsoBaseFileFormat.Boxes.FileType where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box++-- | File Type Box+type FileTypeBox = Box "ftyp"++instance BoxRules "ftyp"++-- | Create a 'FileTypeBox' from a major brand, a minor version and a list of+-- compatible brands+fileTypeBox :: FileType -> FileTypeBox+fileTypeBox = box++-- | Contents of a 'ftyp' box are some 'FourCc' /brands/ and a version.+data FileType =+ FileType {majorBrand :: FourCc+ ,minorVersion :: Word32+ ,compatibleBrands :: [FourCc]}++instance IsBoxContent FileType where+ boxSize (FileType maj ver comps) = boxSize maj + 4 + sum (boxSize <$> comps)+ boxBuilder (FileType maj ver comps) =+ boxBuilder maj <> word32BE ver <> mconcat (boxBuilder <$> comps)
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/MediaData.hs view
@@ -0,0 +1,21 @@+module Data.ByteString.IsoBaseFileFormat.Boxes.MediaData where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box+import qualified Data.ByteString as B++-- | Media data box+type MediaDataBox = Box "mdat"++instance BoxRules "mdat"++-- | Create a 'MediaDataBox' from a strict 'ByteString'+mediaDataBox :: MediaData -> MediaDataBox+mediaDataBox = box++-- | Contents of a 'mdat' box are just bytes from a strict 'ByteString'+newtype MediaData =+ MediaData B.ByteString++instance IsBoxContent MediaData where+ boxSize (MediaData bs) = fromIntegral $ B.length bs+ boxBuilder (MediaData bs) = byteString bs
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/MovieBox.hs view
@@ -0,0 +1,39 @@+-- | Meta data for a presentation of a /movie/.+module Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box++-- Uncomment this to see what the custom compiler errors look like:+--+-- import Data.ByteString.IsoBaseFileFormat.Boxes.Skip+-- xxx :: Box "moov"+-- xxx = movieBox+-- (movieBoxContainer :- skipBox (Skip 100))++-- | The metadata for a presentation, a single 'MovieBox' which occurs only once+-- and top-level. It is pretty empty on it's own, but it contains nested boxes+-- with all the relevant meta data.+type MovieBox = Box "moov"++instance BoxRules "moov" where+ type RequiredNestedBoxes "moov" = '["mvhd", "trak"]++-- | Compose a movie box from the required 'Boxes'.+movieBox :: forall ts. ValidBoxes "moov" ts => Boxes "moov" ts -> Box "moov"+movieBox = boxes++-- | The movie box container, use this to create movie boxes filled with nested+-- boxes, for example:+--+-- > xxx :: Box "moov"+-- > xxx = movieBox+-- > (movieBoxContainer+-- > :- movieHeaderBox (MovieHeader ...)+-- > :- trackBox+-- > (trackBoxContainer+-- > :- trackHeaderBox+-- > :- trackReferenceBox+-- > :- trackGroupingIndication))+--+movieBoxContainer :: Container "moov"+movieBoxContainer = Parent emptyBox
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/ProgressiveDownloadInformation.hs view
@@ -0,0 +1,25 @@+module Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation+ where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box++-- | A Box with progressive download information+type ProgressiveDownloadInformationBox = Box "pdin"++instance BoxRules "pdin"++-- | Create a 'pdin' box+progressiveDownloadInformationBox+ :: ProgressiveDownloadInformation -> ProgressiveDownloadInformationBox+progressiveDownloadInformationBox = fullBox (BoxVersion 0) zeroBits++-- | Information for progressive media data download/playback encompasses the+-- delay for initial playback and expected download bit rate.+data ProgressiveDownloadInformation =+ ProgressiveDownloadInformation {pdinRate :: Word32 -- ^ Effective download bitrate in byte/sec+ ,pdinDelay :: Word32 -- ^ Delay in milli seconds+ }++instance IsBoxContent ProgressiveDownloadInformation where+ boxSize _ = 8+ boxBuilder pdin = word32BE (pdinRate pdin) <> word32BE (pdinDelay pdin)
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/Skip.hs view
@@ -0,0 +1,21 @@+module Data.ByteString.IsoBaseFileFormat.Boxes.Skip where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box++-- | A filler box, the contents are skipped+type SkipBox = Box "skip"++instance BoxRules "skip" where+ type RestrictedTo "skip" = 'Nothing++-- | Create a 'SkipBox' with a given size.+skipBox :: Skip -> SkipBox+skipBox = box++-- | Contents of a 'skip' box are just any number of filler bytes.+newtype Skip =+ Skip Int++instance IsBoxContent Skip where+ boxSize (Skip bs) = fromIntegral bs+ boxBuilder (Skip bs) = mconcat (replicate bs (word8 0))
+ src/Data/ByteString/IsoBaseFileFormat/Builder.hs view
@@ -0,0 +1,11 @@+-- | This module re-exports all modules needed to build /ISOBMFF/ documents.+module Data.ByteString.IsoBaseFileFormat.Builder+ (module Data.ByteString.IsoBaseFileFormat.Builder, module X)+ where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box as X+import Data.ByteString.IsoBaseFileFormat.Boxes.FileType as X+import Data.ByteString.IsoBaseFileFormat.Boxes.MediaData as X+import Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox as X+import Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation as X+import Data.ByteString.IsoBaseFileFormat.Boxes.Skip as X