module Codec.Container.Ogg.Headers (
processHeaders
) where
import qualified Data.Map as Map
import Codec.Container.Ogg.ContentType
import Codec.Container.Ogg.Page
import Codec.Container.Ogg.Track
processHeaders :: ([OggPage] -> [OggPage]) -> [OggPage] -> [OggPage]
processHeaders f gs = (f controlSection) ++ dataSection
where (controlSection, dataSection) = splitHeaders gs
splitHeaders :: [OggPage] -> ([OggPage], [OggPage])
splitHeaders gs = splitHeaders' Map.empty ([], [], gs)
splitHeaders' ::
Map.Map OggTrack [OggPage]
-> ([OggPage], [OggPage], [OggPage])
-> ([OggPage], [OggPage])
splitHeaders' _ (hs, nhs, []) = (hs, nhs)
splitHeaders' seen (hs, nhs, (g:gs))
| isSkeleton = splitHeaders' seen (hs++[g], nhs, gs)
| pageBOS g = splitHeaders' insertSeen (hs++[g], nhs, gs)
| Map.null seen = (hs, nhs++(g:gs))
| notSeen = splitHeaders' seen (hs, nhs++[g], gs)
| lastHeader = splitHeaders' deleteSeen (hs++[g], nhs, gs)
| otherwise = splitHeaders' appendSeen (hs++[g], nhs, gs)
where
t = pageTrack g
insertSeen = Map.insert t [g] seen
appendSeen = Map.insert t tPages seen
deleteSeen = Map.delete t seen
notSeen = Map.notMember t seen
isSkeleton = contentTypeIs skeleton t
lastHeader = nPackets >= nHeaders
nHeaders = trackHeaders t
nPackets = sum $ map pageCompletedPackets tPages
tPages = (Map.findWithDefault [] t seen) ++ [g]