module Codec.FFmpeg.Types where
import Codec.FFmpeg.Enums
import Control.Applicative
import Control.Monad (zipWithM_,when)
import Foreign.C.String (CString)
import Foreign.C.Types
import Foreign.Ptr
import Foreign.Storable
class HasPtr a where
getPtr :: a -> Ptr ()
instance HasPtr (Ptr ()) where getPtr = id
newtype AVFormatContext = AVFormatContext (Ptr ()) deriving (Storable, HasPtr)
class HasNumStreams t where
getNumStreams :: t -> IO CInt
setNumStreams :: t -> CInt -> IO ()
hasNumStreams :: t -> Ptr CInt
class HasStreams t where
getStreams :: t -> IO (Ptr AVStream)
setStreams :: t -> (Ptr AVStream) -> IO ()
hasStreams :: t -> Ptr (Ptr AVStream)
class HasOutputFormat t where
getOutputFormat :: t -> IO AVOutputFormat
setOutputFormat :: t -> AVOutputFormat -> IO ()
hasOutputFormat :: t -> Ptr AVOutputFormat
class HasIOContext t where
getIOContext :: t -> IO AVIOContext
setIOContext :: t -> AVIOContext -> IO ()
hasIOContext :: t -> Ptr AVIOContext
class HasInputFormat t where
getInputFormat :: t -> IO AVInputFormat
setInputFormat :: t -> AVInputFormat -> IO ()
hasInputFormat :: t -> Ptr AVInputFormat
instance HasNumStreams AVFormatContext where
getNumStreams = (\hsc_ptr -> peekByteOff hsc_ptr 44) . getPtr
setNumStreams = (\hsc_ptr -> pokeByteOff hsc_ptr 44) . getPtr
hasNumStreams = (\hsc_ptr -> hsc_ptr `plusPtr` 44) . getPtr
instance HasStreams AVFormatContext where
getStreams = (\hsc_ptr -> peekByteOff hsc_ptr 48) . getPtr
setStreams = (\hsc_ptr -> pokeByteOff hsc_ptr 48) . getPtr
hasStreams = (\hsc_ptr -> hsc_ptr `plusPtr` 48) . getPtr
instance HasOutputFormat AVFormatContext where
getOutputFormat = (\hsc_ptr -> peekByteOff hsc_ptr 16) . getPtr
setOutputFormat = (\hsc_ptr -> pokeByteOff hsc_ptr 16) . getPtr
hasOutputFormat = (\hsc_ptr -> hsc_ptr `plusPtr` 16) . getPtr
instance HasInputFormat AVFormatContext where
getInputFormat = (\hsc_ptr -> peekByteOff hsc_ptr 8) . getPtr
setInputFormat = (\hsc_ptr -> pokeByteOff hsc_ptr 8) . getPtr
hasInputFormat = (\hsc_ptr -> hsc_ptr `plusPtr` 8) . getPtr
instance HasIOContext AVFormatContext where
getIOContext = (\hsc_ptr -> peekByteOff hsc_ptr 32) . getPtr
setIOContext = (\hsc_ptr -> pokeByteOff hsc_ptr 32) . getPtr
hasIOContext = (\hsc_ptr -> hsc_ptr `plusPtr` 32) . getPtr
setFilename :: AVFormatContext -> String -> IO ()
setFilename ctx fn =
do let ptr = getPtr ctx
dst = ((\hsc_ptr -> hsc_ptr `plusPtr` 56)) ptr
bytes = map (fromIntegral . fromEnum) fn
zipWithM_ (pokeElemOff dst) bytes [(0 :: CInt) ..]
foreign import ccall "av_input_video_device_next"
av_input_video_device_next :: AVInputFormat -> IO AVInputFormat
setCamera :: AVFormatContext -> IO ()
setCamera ctx = do
ipt <- getCameraAVInputFormat (AVInputFormat nullPtr)
setInputFormat ctx ipt
where
getCameraAVInputFormat :: AVInputFormat -> IO AVInputFormat
getCameraAVInputFormat p = do
nxt <- av_input_video_device_next p
when (nullPtr == getPtr nxt) (error "No video input device found.")
return nxt
foreign import ccall "avformat_alloc_context"
avformat_alloc_context :: IO (Ptr ())
mallocAVFormatContext :: IO AVFormatContext
mallocAVFormatContext = AVFormatContext <$> avformat_alloc_context
newtype AVCodecContext = AVCodecContext (Ptr ()) deriving (Storable, HasPtr)
class HasBitRate t where
getBitRate :: t -> IO CInt
setBitRate :: t -> CInt -> IO ()
hasBitRate :: t -> Ptr CInt
instance HasBitRate AVCodecContext where
getBitRate = (\hsc_ptr -> peekByteOff hsc_ptr 96) . getPtr
setBitRate = (\hsc_ptr -> pokeByteOff hsc_ptr 96) . getPtr
hasBitRate = (\hsc_ptr -> hsc_ptr `plusPtr` 96) . getPtr
class HasWidth t where
getWidth :: t -> IO CInt
setWidth :: t -> CInt -> IO ()
hasWidth :: t -> Ptr CInt
class HasHeight t where
getHeight :: t -> IO CInt
setHeight :: t -> CInt -> IO ()
hasHeight :: t -> Ptr CInt
class HasTimeBase t where
getTimeBase :: t -> IO AVRational
setTimeBase :: t -> AVRational -> IO ()
hasTimeBase :: t -> Ptr AVRational
class HasGopSize t where
getGopSize :: t -> IO CInt
setGopSize :: t -> CInt -> IO ()
hasGopSize :: t -> Ptr CInt
class HasPixelFormat t where
getPixelFormat :: t -> IO AVPixelFormat
setPixelFormat :: t -> AVPixelFormat -> IO ()
hasPixelFormat :: t -> Ptr AVPixelFormat
class HasCodecFlags t where
getCodecFlags :: t -> IO CodecFlag
setCodecFlags :: t -> CodecFlag -> IO ()
hasCodecFlags :: t -> Ptr CodecFlag
class HasCodecID t where
getCodecID :: t -> IO AVCodecID
setCodecID :: t -> AVCodecID -> IO ()
hasCodecID :: t -> Ptr AVCodecID
class HasPrivData t where
getPrivData :: t -> IO (Ptr ())
setPrivData :: t -> (Ptr ()) -> IO ()
hasPrivData :: t -> Ptr (Ptr ())
instance HasWidth AVCodecContext where
getWidth = (\hsc_ptr -> peekByteOff hsc_ptr 156) . getPtr
setWidth = (\hsc_ptr -> pokeByteOff hsc_ptr 156) . getPtr
hasWidth = (\hsc_ptr -> hsc_ptr `plusPtr` 156) . getPtr
instance HasHeight AVCodecContext where
getHeight = (\hsc_ptr -> peekByteOff hsc_ptr 160) . getPtr
setHeight = (\hsc_ptr -> pokeByteOff hsc_ptr 160) . getPtr
hasHeight = (\hsc_ptr -> hsc_ptr `plusPtr` 160) . getPtr
instance HasTimeBase AVCodecContext where
getTimeBase = (\hsc_ptr -> peekByteOff hsc_ptr 140) . getPtr
setTimeBase = (\hsc_ptr -> pokeByteOff hsc_ptr 140) . getPtr
hasTimeBase = (\hsc_ptr -> hsc_ptr `plusPtr` 140) . getPtr
instance HasGopSize AVCodecContext where
getGopSize = (\hsc_ptr -> peekByteOff hsc_ptr 172) . getPtr
setGopSize = (\hsc_ptr -> pokeByteOff hsc_ptr 172) . getPtr
hasGopSize = (\hsc_ptr -> hsc_ptr `plusPtr` 172) . getPtr
instance HasPixelFormat AVCodecContext where
getPixelFormat = (\hsc_ptr -> peekByteOff hsc_ptr 176) . getPtr
setPixelFormat = (\hsc_ptr -> pokeByteOff hsc_ptr 176) . getPtr
hasPixelFormat = (\hsc_ptr -> hsc_ptr `plusPtr` 176) . getPtr
instance HasCodecFlags AVCodecContext where
getCodecFlags = (\hsc_ptr -> peekByteOff hsc_ptr 116) . getPtr
setCodecFlags = (\hsc_ptr -> pokeByteOff hsc_ptr 116) . getPtr
hasCodecFlags = (\hsc_ptr -> hsc_ptr `plusPtr` 116) . getPtr
instance HasCodecID AVCodecContext where
getCodecID = (\hsc_ptr -> peekByteOff hsc_ptr 56) . getPtr
setCodecID = (\hsc_ptr -> pokeByteOff hsc_ptr 56) . getPtr
hasCodecID = (\hsc_ptr -> hsc_ptr `plusPtr` 56) . getPtr
instance HasPrivData AVCodecContext where
getPrivData = (\hsc_ptr -> peekByteOff hsc_ptr 72) . getPtr
setPrivData = (\hsc_ptr -> pokeByteOff hsc_ptr 72) . getPtr
hasPrivData = (\hsc_ptr -> hsc_ptr `plusPtr` 72) . getPtr
newtype AVStream = AVStream (Ptr ()) deriving (Storable, HasPtr)
class HasId t where
getId :: t -> IO CInt
setId :: t -> CInt -> IO ()
hasId :: t -> Ptr CInt
class HasCodecContext t where
getCodecContext :: t -> IO AVCodecContext
setCodecContext :: t -> AVCodecContext -> IO ()
hasCodecContext :: t -> Ptr AVCodecContext
class HasStreamIndex t where
getStreamIndex :: t -> IO CInt
setStreamIndex :: t -> CInt -> IO ()
hasStreamIndex :: t -> Ptr CInt
instance HasId AVStream where
getId = (\hsc_ptr -> peekByteOff hsc_ptr 4) . getPtr
setId = (\hsc_ptr -> pokeByteOff hsc_ptr 4) . getPtr
hasId = (\hsc_ptr -> hsc_ptr `plusPtr` 4) . getPtr
instance HasTimeBase AVStream where
getTimeBase = (\hsc_ptr -> peekByteOff hsc_ptr 48) . getPtr
setTimeBase = (\hsc_ptr -> pokeByteOff hsc_ptr 48) . getPtr
hasTimeBase = (\hsc_ptr -> hsc_ptr `plusPtr` 48) . getPtr
instance HasCodecContext AVStream where
getCodecContext = (\hsc_ptr -> peekByteOff hsc_ptr 8) . getPtr
setCodecContext = (\hsc_ptr -> pokeByteOff hsc_ptr 8) . getPtr
hasCodecContext = (\hsc_ptr -> hsc_ptr `plusPtr` 8) . getPtr
instance HasStreamIndex AVStream where
getStreamIndex = (\hsc_ptr -> peekByteOff hsc_ptr 0) . getPtr
setStreamIndex = (\hsc_ptr -> pokeByteOff hsc_ptr 0) . getPtr
hasStreamIndex = (\hsc_ptr -> hsc_ptr `plusPtr` 0) . getPtr
newtype AVCodec = AVCodec (Ptr ()) deriving (Storable, HasPtr)
class HasLongName t where
getLongName :: t -> IO CString
setLongName :: t -> CString -> IO ()
hasLongName :: t -> Ptr CString
class HasName t where
getName :: t -> IO CString
setName :: t -> CString -> IO ()
hasName :: t -> Ptr CString
class HasPixelFormats t where
getPixelFormats :: t -> IO (Ptr AVPixelFormat)
setPixelFormats :: t -> (Ptr AVPixelFormat) -> IO ()
hasPixelFormats :: t -> Ptr (Ptr AVPixelFormat)
instance HasLongName AVCodec where
getLongName = (\hsc_ptr -> peekByteOff hsc_ptr 8) . getPtr
setLongName = (\hsc_ptr -> pokeByteOff hsc_ptr 8) . getPtr
hasLongName = (\hsc_ptr -> hsc_ptr `plusPtr` 8) . getPtr
instance HasName AVCodec where
getName = (\hsc_ptr -> peekByteOff hsc_ptr 0) . getPtr
setName = (\hsc_ptr -> pokeByteOff hsc_ptr 0) . getPtr
hasName = (\hsc_ptr -> hsc_ptr `plusPtr` 0) . getPtr
instance HasCodecID AVCodec where
getCodecID = (\hsc_ptr -> peekByteOff hsc_ptr 20) . getPtr
setCodecID = (\hsc_ptr -> pokeByteOff hsc_ptr 20) . getPtr
hasCodecID = (\hsc_ptr -> hsc_ptr `plusPtr` 20) . getPtr
instance HasPixelFormats AVCodec where
getPixelFormats = (\hsc_ptr -> peekByteOff hsc_ptr 40) . getPtr
setPixelFormats = (\hsc_ptr -> pokeByteOff hsc_ptr 40) . getPtr
hasPixelFormats = (\hsc_ptr -> hsc_ptr `plusPtr` 40) . getPtr
newtype AVDictionary = AVDictionary (Ptr ()) deriving (Storable, HasPtr)
newtype AVFrame = AVFrame (Ptr ()) deriving (Storable, HasPtr)
class HasPts t where
getPts :: t -> IO CLong
setPts :: t -> CLong -> IO ()
hasPts :: t -> Ptr CLong
class HasPktPts t where
getPktPts :: t -> IO CLong
setPktPts :: t -> CLong -> IO ()
hasPktPts :: t -> Ptr CLong
class HasLineSize t where
getLineSize :: t -> IO CInt
setLineSize :: t -> CInt -> IO ()
hasLineSize :: t -> Ptr CInt
instance HasPixelFormat AVFrame where
getPixelFormat = (\hsc_ptr -> peekByteOff hsc_ptr 116) . getPtr
setPixelFormat = (\hsc_ptr -> pokeByteOff hsc_ptr 116) . getPtr
hasPixelFormat = (\hsc_ptr -> hsc_ptr `plusPtr` 116) . getPtr
instance HasWidth AVFrame where
getWidth = (\hsc_ptr -> peekByteOff hsc_ptr 104) . getPtr
setWidth = (\hsc_ptr -> pokeByteOff hsc_ptr 104) . getPtr
hasWidth = (\hsc_ptr -> hsc_ptr `plusPtr` 104) . getPtr
instance HasHeight AVFrame where
getHeight = (\hsc_ptr -> peekByteOff hsc_ptr 108) . getPtr
setHeight = (\hsc_ptr -> pokeByteOff hsc_ptr 108) . getPtr
hasHeight = (\hsc_ptr -> hsc_ptr `plusPtr` 108) . getPtr
instance HasLineSize AVFrame where
getLineSize = (\hsc_ptr -> peekByteOff hsc_ptr 64) . getPtr
setLineSize = (\hsc_ptr -> pokeByteOff hsc_ptr 64) . getPtr
hasLineSize = (\hsc_ptr -> hsc_ptr `plusPtr` 64) . getPtr
instance HasPts AVFrame where
getPts = (\hsc_ptr -> peekByteOff hsc_ptr 136) . getPtr
setPts = (\hsc_ptr -> pokeByteOff hsc_ptr 136) . getPtr
hasPts = (\hsc_ptr -> hsc_ptr `plusPtr` 136) . getPtr
instance HasPktPts AVFrame where
getPktPts = (\hsc_ptr -> peekByteOff hsc_ptr 144) . getPtr
setPktPts = (\hsc_ptr -> pokeByteOff hsc_ptr 144) . getPtr
hasPktPts = (\hsc_ptr -> hsc_ptr `plusPtr` 144) . getPtr
instance HasData AVFrame where
getData = (\hsc_ptr -> peekByteOff hsc_ptr 0) . getPtr
setData = (\hsc_ptr -> pokeByteOff hsc_ptr 0) . getPtr
hasData = (\hsc_ptr -> hsc_ptr `plusPtr` 0) . getPtr
newtype AVPicture = AVPicture (Ptr ()) deriving (Storable, HasPtr)
instance HasData AVPicture where
getData = (\hsc_ptr -> peekByteOff hsc_ptr 0) . getPtr
setData = (\hsc_ptr -> pokeByteOff hsc_ptr 0) . getPtr
hasData = (\hsc_ptr -> hsc_ptr `plusPtr` 0) . getPtr
newtype SwsContext = SwsContext (Ptr ()) deriving (Storable, HasPtr)
newtype AVOutputFormat = AVOutputFormat (Ptr ()) deriving (Storable, HasPtr)
class HasFormatFlags t where
getFormatFlags :: t -> IO FormatFlag
setFormatFlags :: t -> FormatFlag -> IO ()
hasFormatFlags :: t -> Ptr FormatFlag
class HasVideoCodecID t where
getVideoCodecID :: t -> IO AVCodecID
setVideoCodecID :: t -> AVCodecID -> IO ()
hasVideoCodecID :: t -> Ptr AVCodecID
instance HasFormatFlags AVOutputFormat where
getFormatFlags = (\hsc_ptr -> peekByteOff hsc_ptr 44) . getPtr
setFormatFlags = (\hsc_ptr -> pokeByteOff hsc_ptr 44) . getPtr
hasFormatFlags = (\hsc_ptr -> hsc_ptr `plusPtr` 44) . getPtr
instance HasVideoCodecID AVOutputFormat where
getVideoCodecID = (\hsc_ptr -> peekByteOff hsc_ptr 36) . getPtr
setVideoCodecID = (\hsc_ptr -> pokeByteOff hsc_ptr 36) . getPtr
hasVideoCodecID = (\hsc_ptr -> hsc_ptr `plusPtr` 36) . getPtr
newtype AVInputFormat = AVInputFormat (Ptr ()) deriving (Storable, HasPtr)
newtype AVClass = AVClass (Ptr ()) deriving (Storable, HasPtr)
class HasAVClass t where
getAVClass :: t -> IO AVClass
setAVClass :: t -> AVClass -> IO ()
hasAVClass :: t -> Ptr AVClass
instance HasAVClass AVInputFormat where
getAVClass = (\hsc_ptr -> peekByteOff hsc_ptr 40) . getPtr
setAVClass = (\hsc_ptr -> pokeByteOff hsc_ptr 40) . getPtr
hasAVClass = (\hsc_ptr -> hsc_ptr `plusPtr` 40) . getPtr
getAVCategory :: AVInputFormat -> IO Category
getAVCategory aif =
do c <- getAVClass aif
if nullPtr == getPtr c
then return (Category (1))
else Category <$> peek (((\hsc_ptr -> hsc_ptr `plusPtr` 56)) $ castPtr $ getPtr c)
newtype Category = Category CInt deriving (Eq,Ord,Show,Read,Enum)
avClassCategoryNa :: Category
avClassCategoryNa = Category 0
avClassCategoryInput :: Category
avClassCategoryInput = Category 1
avClassCategoryOutput :: Category
avClassCategoryOutput = Category 2
avClassCategoryMuxer :: Category
avClassCategoryMuxer = Category 3
avClassCategoryDemuxer :: Category
avClassCategoryDemuxer = Category 4
avClassCategoryEncoder :: Category
avClassCategoryEncoder = Category 5
avClassCategoryDecoder :: Category
avClassCategoryDecoder = Category 6
avClassCategoryFilter :: Category
avClassCategoryFilter = Category 7
avClassCategoryBitstreamFilter :: Category
avClassCategoryBitstreamFilter = Category 8
avClassCategorySwscaler :: Category
avClassCategorySwscaler = Category 9
avClassCategorySwresampler :: Category
avClassCategorySwresampler = Category 10
avClassCategoryDeviceVideoOutput :: Category
avClassCategoryDeviceVideoOutput = Category 40
avClassCategoryDeviceVideoInput :: Category
avClassCategoryDeviceVideoInput = Category 41
avClassCategoryDeviceAudioOutput :: Category
avClassCategoryDeviceAudioOutput = Category 42
avClassCategoryDeviceAudioInput :: Category
avClassCategoryDeviceAudioInput = Category 43
avClassCategoryDeviceOutput :: Category
avClassCategoryDeviceOutput = Category 44
avClassCategoryDeviceInput :: Category
avClassCategoryDeviceInput = Category 45
avClassCategoryNb :: Category
avClassCategoryNb = Category 46
newtype AVIOContext = AVIOContext (Ptr ()) deriving (Storable, HasPtr)
newtype AVPacket = AVPacket (Ptr ()) deriving (Storable, HasPtr)
class HasData t where
getData :: t -> IO (Ptr ())
setData :: t -> (Ptr ()) -> IO ()
hasData :: t -> Ptr (Ptr ())
class HasSize t where
getSize :: t -> IO CInt
setSize :: t -> CInt -> IO ()
hasSize :: t -> Ptr CInt
class HasPacketFlags t where
getPacketFlags :: t -> IO PacketFlag
setPacketFlags :: t -> PacketFlag -> IO ()
hasPacketFlags :: t -> Ptr PacketFlag
class HasDts t where
getDts :: t -> IO CLong
setDts :: t -> CLong -> IO ()
hasDts :: t -> Ptr CLong
instance HasData AVPacket where
getData = (\hsc_ptr -> peekByteOff hsc_ptr 24) . getPtr
setData = (\hsc_ptr -> pokeByteOff hsc_ptr 24) . getPtr
hasData = (\hsc_ptr -> hsc_ptr `plusPtr` 24) . getPtr
instance HasSize AVPacket where
getSize = (\hsc_ptr -> peekByteOff hsc_ptr 32) . getPtr
setSize = (\hsc_ptr -> pokeByteOff hsc_ptr 32) . getPtr
hasSize = (\hsc_ptr -> hsc_ptr `plusPtr` 32) . getPtr
instance HasPacketFlags AVPacket where
getPacketFlags = (\hsc_ptr -> peekByteOff hsc_ptr 40) . getPtr
setPacketFlags = (\hsc_ptr -> pokeByteOff hsc_ptr 40) . getPtr
hasPacketFlags = (\hsc_ptr -> hsc_ptr `plusPtr` 40) . getPtr
instance HasStreamIndex AVPacket where
getStreamIndex = (\hsc_ptr -> peekByteOff hsc_ptr 36) . getPtr
setStreamIndex = (\hsc_ptr -> pokeByteOff hsc_ptr 36) . getPtr
hasStreamIndex = (\hsc_ptr -> hsc_ptr `plusPtr` 36) . getPtr
instance HasPts AVPacket where
getPts = (\hsc_ptr -> peekByteOff hsc_ptr 8) . getPtr
setPts = (\hsc_ptr -> pokeByteOff hsc_ptr 8) . getPtr
hasPts = (\hsc_ptr -> hsc_ptr `plusPtr` 8) . getPtr
instance HasDts AVPacket where
getDts = (\hsc_ptr -> peekByteOff hsc_ptr 16) . getPtr
setDts = (\hsc_ptr -> pokeByteOff hsc_ptr 16) . getPtr
hasDts = (\hsc_ptr -> hsc_ptr `plusPtr` 16) . getPtr
packetSize :: Int
packetSize = (88)
pictureSize :: Int
pictureSize = (96)
data AVRational = AVRational { numerator :: CInt
, denomenator :: CInt } deriving Show
instance Storable AVRational where
sizeOf _ = (8)
alignment _ = (8)
peek ptr = AVRational <$> ((\hsc_ptr -> peekByteOff hsc_ptr 0)) ptr
<*> ((\hsc_ptr -> peekByteOff hsc_ptr 4)) ptr
poke ptr (AVRational n d) = do ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) ptr n
((\hsc_ptr -> pokeByteOff hsc_ptr 4)) ptr d
foreign import ccall "av_rescale_rnd"
av_rescale_rnd :: CLong -> CLong -> CLong -> AVRoundMode -> CLong
av_q2d :: AVRational -> CDouble
av_q2d r = fromIntegral (numerator r) / fromIntegral (denomenator r)
av_rescale_q :: CLong -> AVRational -> AVRational -> CLong
av_rescale_q a bq cq = av_rescale_rnd a b c avRoundNearInf
where b = fromIntegral (numerator bq) * fromIntegral (denomenator cq)
c = fromIntegral (numerator cq) * fromIntegral (denomenator bq)
data AVFrac = AVFrac { fracVal :: CLong
, fracNum :: CLong
, fracDen :: CLong } deriving Show
instance Storable AVFrac where
sizeOf _ = (24)
alignment _ = (24)
peek ptr = AVFrac <$> ((\hsc_ptr -> peekByteOff hsc_ptr 0)) ptr
<*> ((\hsc_ptr -> peekByteOff hsc_ptr 8)) ptr
<*> ((\hsc_ptr -> peekByteOff hsc_ptr 16)) ptr
poke ptr (AVFrac v n d) = do ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) ptr v
((\hsc_ptr -> pokeByteOff hsc_ptr 8)) ptr n
((\hsc_ptr -> pokeByteOff hsc_ptr 16)) ptr d
data InputSource = File FilePath | Camera String CameraConfig
deriving (Eq, Ord, Show, Read)
data CameraConfig =
CameraConfig { framerate :: Maybe Int
, resolution :: Maybe (Int,Int)
}
deriving (Eq,Ord,Show,Read)
defaultCameraConfig :: CameraConfig
defaultCameraConfig = CameraConfig (Just 30) Nothing