packages feed

ffmpeg-light 0.10.0 → 0.11.0

raw patch · 9 files changed

+95/−116 lines, 9 filesdep ~basedep ~transformers

Dependency ranges changed: base, transformers

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+# 0.11.0++* Query stream duration (Matthias Treydte)+* Initial support for verbosity control; defaults to quiet+   * Can be changed with the new `setLogLevel` function+ # 0.10. 0  * Fix encoder bug that created a single black frame at the start of
demo/Main.hs view
@@ -66,8 +66,9 @@  testCamera :: IO () testCamera =-  do initFFmpeg-     (getFrame, cleanup) <- imageReader (Camera "0:0")+  do initFFmpeg -- Defaults to quiet (minimal) logging+     -- setLogLevel avLogInfo -- Restore standard ffmpeg logging+     (getFrame, cleanup) <- imageReader (Camera "0:0" defaultCameraConfig)      frame1 <- getFrame      case frame1 of        img@(Just (Image w h _)) ->
ffmpeg-light.cabal view
@@ -1,5 +1,5 @@ name:                ffmpeg-light-version:             0.10.0+version:             0.11.0 synopsis:            Minimal bindings to the FFmpeg library.  description:         Stream frames from an encoded video, or stream frames to@@ -15,17 +15,18 @@                      > go = do (getFrame, cleanup) <- imageReader "myVideo.mov"                      >         (fmap ImageRGB8 <$> getFrame) <* cleanup                      .-                     Tested on OS X 10.11.2 with <http://www.ffmpeg.org FFmpeg> 2.8.3-                     installed via <http://brew.sh homebrew>.+                     Tested with FFmpeg 2.7 - 3.0  license:             BSD3 license-file:        LICENSE author:              Anthony Cowley maintainer:          acowley@gmail.com copyright:           Copyright (C) 2014 Anthony Cowley+homepage:            http://github.com/acowley/ffmpeg-light+bug-reports:         http://github.com/acowley/ffmpeg-light/issues category:            Codec build-type:          Simple-extra-source-files:  src/hscMacros.h, src/nameCompat.h, CHANGELOG.md+extra-source-files:  src/hscMacros.h, CHANGELOG.md cabal-version:       >=1.10  source-repository head@@ -55,11 +56,11 @@                        Codec.FFmpeg.Internal.Debug,                        Codec.FFmpeg.Internal.Linear   build-tools:         hsc2hs-  build-depends:       base >=4.6 && < 5,+  build-depends:       base >=4.6 && < 4.10,                        either,                        exceptions,                        vector >= 0.10.9 && < 0.12,-                       transformers >= 0.4.1 && < 0.5,+                       transformers >= 0.4.1 && < 0.6,                        mtl >= 2.2.1 && < 2.3,                        JuicyPixels >= 3.1 && < 3.3   pkgconfig-depends:   libavutil, libavformat, libavcodec, libswscale, libavdevice
src/Codec/FFmpeg.hs view
@@ -2,7 +2,7 @@ -- | Interface to initialize FFmpeg, decode video files, encode video -- files, and convert decoded image frames to JuicyPixels images. module Codec.FFmpeg (-- * Initialization-                     initFFmpeg, +                     initFFmpeg, setLogLevel,                      -- * Decoding                      imageReader, imageReaderTime,                      imageReaderT, imageReaderTimeT,@@ -16,14 +16,22 @@ import Codec.FFmpeg.Enums import Codec.FFmpeg.Juicy import Codec.FFmpeg.Types+import Foreign.C.Types (CInt(..))  foreign import ccall "av_register_all" av_register_all :: IO () foreign import ccall "avdevice_register_all" avdevice_register_all :: IO () --- foreign import ccall "avcodec_register_all" avcodec_register_all :: IO ()+-- foreign import ccall "avcodec_register_all" avcodec_register_all :: IO ( --- | Initialize FFmpeg by registering all known codecs. This /must/--- be called before using other FFmpeg functions.-initFFmpeg :: IO ()-initFFmpeg = av_register_all >> avdevice_register_all+foreign import ccall "av_log_set_level" av_log_set_level :: CInt -> IO () +-- | Log output is sent to stderr.+setLogLevel :: LogLevel -> IO ()+setLogLevel (LogLevel l) = av_log_set_level l++-- | Initialize FFmpeg by registering all known codecs. This /must/ be+-- called before using other FFmpeg functions. The debug level is+-- initially set to @quiet@. If you would like the standard ffmpeg+-- debug level, call @setLogLevel avLogInfo@ after @initFFmpeg@.+initFFmpeg :: IO ()+initFFmpeg = av_register_all >> avdevice_register_all >> setLogLevel avLogQuiet
src/Codec/FFmpeg/Decode.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ForeignFunctionInterface, FlexibleContexts #-}+{-# LANGUAGE ForeignFunctionInterface, FlexibleContexts, RecordWildCards #-} -- | Video decoding API. Includes FFI declarations for the underlying -- FFmpeg functions, wrappers for these functions that wrap error -- condition checking, and high level Haskellized interfaces.@@ -9,7 +9,7 @@ import Codec.FFmpeg.Types import Control.Applicative import Control.Arrow (first)-import Control.Monad (when)+import Control.Monad (when, void) import Control.Monad.Error.Class import Control.Monad.IO.Class import Control.Monad.Trans.Maybe@@ -23,11 +23,11 @@  -- * FFI Declarations -foreign import ccall "avformat_open_input" +foreign import ccall "avformat_open_input"   avformat_open_input :: Ptr AVFormatContext -> CString -> Ptr ()                       -> Ptr AVDictionary -> IO CInt -foreign import ccall "avformat_find_stream_info" +foreign import ccall "avformat_find_stream_info"   avformat_find_stream_info :: AVFormatContext -> Ptr () -> IO CInt  foreign import ccall "av_find_best_stream"@@ -40,9 +40,6 @@ foreign import ccall "avcodec_find_decoder_by_name"   avcodec_find_decoder_by_name :: CString -> IO AVCodec -foreign import ccall "avcodec_get_frame_defaults"-  avcodec_get_frame_defaults :: AVFrame -> IO ()- foreign import ccall "avpicture_get_size"   avpicture_get_size :: AVPixelFormat -> CInt -> CInt -> IO CInt @@ -71,33 +68,42 @@ -- * FFmpeg Decoding Interface  -- | Open the first video input device enumerated by FFMPEG.-openCamera :: (MonadIO m, MonadError String m) => String -> m AVFormatContext-openCamera cam =+openCamera :: (MonadIO m, MonadError String m) => String -> CameraConfig -> m AVFormatContext+openCamera cam cfg =   wrapIOError . alloca $ \ctx ->     withCString cam $ \cstr ->       do avPtr <- mallocAVFormatContext          setupCamera avPtr cam          poke ctx avPtr          r <- alloca $ \dict -> do-                dictSet dict "framerate" "30"+                setConfig dict cfg                 avformat_open_input ctx cstr nullPtr dict          when (r /= 0) (fail $ "ffmpeg failed opening file: " ++ show r)          peek ctx   where+    run :: (a -> IO b) -> Maybe a -> IO ()+    run _ Nothing  = return ()+    run f (Just x) = void (f x)++    setConfig :: Ptr AVDictionary -> CameraConfig -> IO ()+    setConfig dict (CameraConfig {..}) =+      do run (dictSet dict "framerate" . show) framerate+         run (\(w,h) -> dictSet dict "video_size" (show w ++ "x" ++ show h)) resolution+     setupCamera :: AVFormatContext -> String -> IO ()-    setupCamera avfc c = do-        setCamera avfc-        setFilename avfc c+    setupCamera avfc c =+      do setCamera avfc+         setFilename avfc c  openInput :: (MonadIO m, MonadError String m) => InputSource -> m AVFormatContext openInput ipt =   case ipt of     File fileName -> openFile fileName-    Camera cam    -> openCamera cam+    Camera cam cf -> openCamera cam cf  -- | Open an input media file. openFile :: (MonadIO m, MonadError String m) => String -> m AVFormatContext-openFile filename = +openFile filename =   wrapIOError . alloca $ \ctx ->     withCString filename $ \cstr ->       do poke (castPtr ctx) nullPtr@@ -112,7 +118,7 @@  -- | Find a codec given by name. findDecoder :: (MonadIO m, MonadError String m) => String -> m AVCodec-findDecoder name = +findDecoder name =   do r <- liftIO $ withCString name avcodec_find_decoder_by_name      when (getPtr r == nullPtr)           (throwError $ "Unsupported codec: " ++ show name)@@ -121,7 +127,7 @@ -- | Read packets of a media file to get stream information. This is -- useful for file formats with no headers such as MPEG. checkStreams :: (MonadIO m, MonadError String m) => AVFormatContext -> m ()-checkStreams ctx = +checkStreams ctx =   do r <- liftIO $ avformat_find_stream_info ctx nullPtr      when (r < 0) (throwError "Couldn't find stream information") @@ -154,7 +160,7 @@ -- 'AVCodec'. **NOTE**: This function is not thread safe! openCodec :: (MonadIO m, MonadError String m)           => AVCodecContext -> AVCodec -> m AVDictionary-openCodec ctx cod = +openCodec ctx cod =   wrapIOError . alloca $ \dict -> do     poke dict (AVDictionary nullPtr)     r <- open_codec ctx cod dict@@ -177,7 +183,7 @@      prepareReader inputContext vidStreamIndex dstFmt ctx  -- | Read RGB frames with the result in the 'MaybeT' transformer.--- +-- -- > frameReaderT = fmap (first MaybeT) . frameReader frameReaderT :: (Functor m, MonadIO m, MonadError String m)              => InputSource -> m (MaybeT IO AVFrame, IO ())@@ -197,7 +203,7 @@      (reader, cleanup) <- prepareReader inputContext vidStreamIndex dstFmt ctx      AVRational num den <- liftIO $ getTimeBase vidStream      let (numl, dend) = (fromIntegral num, fromIntegral den)-         frameTime' frame = +         frameTime' frame =            do n <- getPts frame               return $ fromIntegral (n * numl) / dend          readTS = do frame <- reader@@ -209,7 +215,7 @@  -- | Read time stamped RGB frames with the result in the 'MaybeT' -- transformer.--- +-- -- > frameReaderT = fmap (first MaybeT) . frameReader frameReaderTimeT :: (Functor m, MonadIO m, MonadError String m)                  => InputSource -> m (MaybeT IO (AVFrame, Double), IO ())
src/Codec/FFmpeg/Enums.hsc view
@@ -11,14 +11,6 @@ #include <libavutil/mathematics.h> #include <libswscale/swscale.h> -#ifndef PIX_FMT_RGBA64--- WARNING: Fragile! This pixel format is not defined in older--- versions. Note that many FFI calls will fail at runtime with older--- versions, so all this does is let us the haskell code.-#warning "This version of libav/ffmpeg is too old. It is not likely to work."-#include "nameCompat.h"-#endif- newtype AVMediaType = AVMediaType CInt deriving (Eq, Storable) #enum AVMediaType,AVMediaType \  , AVMEDIA_TYPE_VIDEO\@@ -220,3 +212,16 @@ #enum PacketFlag, PacketFlag \  , AV_PKT_FLAG_KEY\  , AV_PKT_FLAG_CORRUPT++newtype LogLevel = LogLevel CInt deriving (Eq, Bits, Storable)+#enum LogLevel, LogLevel \+ , AV_LOG_QUIET\+ , AV_LOG_PANIC\+ , AV_LOG_FATAL\+ , AV_LOG_ERROR\+ , AV_LOG_WARNING\+ , AV_LOG_INFO\+ , AV_LOG_VERBOSE\+ , AV_LOG_DEBUG\+ , AV_LOG_TRACE\+ , AV_LOG_MAX_OFFSET
src/Codec/FFmpeg/Probe.hsc view
@@ -6,13 +6,13 @@  module Codec.FFmpeg.Probe (     -- * Files-    withAvFile, nbStreams, formatName, formatMetadata,+    withAvFile, nbStreams, formatName, formatMetadata, duration,      -- * Streams     AvStreamT, withStream, codecContext, codecName,     codecMediaTypeName, streamBitrate, streamMetadata,-    codec,-    +    codec, streamImageSize,+     -- * Dictionaries     dictFoldM_     ) where@@ -21,6 +21,7 @@ import Control.Monad.Catch ( MonadMask, finally ) import Control.Monad.Reader import Control.Monad.Trans.Either+import Data.Int ( Int64 ) import Foreign.C.String ( CString, peekCString, withCString ) import Foreign.C.Types ( CInt(..) ) import Foreign.Marshal.Utils ( with )@@ -66,6 +67,9 @@     (#peek AVInputFormat, name) >>=     peekCString +duration :: MonadIO m => AvFormat m Int64+duration = ask >>= \ctx -> liftIO $ (#peek AVFormatContext, duration) (getPtr ctx)+ formatMetadata :: MonadIO m => AvFormat m AVDictionary formatMetadata = ask >>= liftIO . (#peek AVFormatContext, metadata) . getPtr @@ -116,6 +120,13 @@ streamBitrate :: MonadIO m => AVCodecContext -> AvStreamT m Int streamBitrate cctx = liftIO $ getBitRate cctx >>= return . fromIntegral +-- |+-- Gives the (width, height) of a video stream in pixels, not accounting for the pixel aspect ratio.+streamImageSize :: MonadIO m => AVCodecContext -> AvStreamT m (Int, Int)+streamImageSize cctx = liftIO $ (,)+    <$> liftM fromIntegral (getWidth cctx)+    <*> liftM fromIntegral (getHeight cctx)+ streamMetadata :: MonadIO m => AvStreamT m AVDictionary streamMetadata = ask >>= liftIO . (#peek AVStream, metadata) . getPtr @@ -163,4 +174,3 @@  foreign import ccall "av_dict_get"   av_dict_get :: AVDictionary -> CString -> Ptr () -> CInt -> IO (Ptr ())-  
src/Codec/FFmpeg/Types.hsc view
@@ -216,7 +216,16 @@                                (#poke AVFrac, den) ptr d  -- | The input source can be a file or a camera.  When using 'Camera',--- frequently in the form @Camera "0:0"@, the first input video device+-- frequently in the form @Camera "0:0" defaultCameraConfig@, the first input video device -- enumerated by libavdevice is selected.-data InputSource = File FilePath | Camera String+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
− src/nameCompat.h
@@ -1,67 +0,0 @@-/* Older versions of libav (and perhaps ffmpeg) used a different-   naming scheme for constants. Since distributions like Ubuntu 12.04-   are locked down with these old versions, we hack in support for the-   newer constant names. */--#define AV_PIX_FMT_NONE PIX_FMT_NONE-#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24-#define AV_PIX_FMT_RGBA PIX_FMT_RGBA-#define AV_PIX_FMT_BGRA PIX_FMT_BGRA-#define AV_PIX_FMT_Y400A PIX_FMT_Y400A-#define AV_PIX_FMT_RGB32 PIX_FMT_RGB32-#define AV_PIX_FMT_RGB32_1 PIX_FMT_RGB32_1-#define AV_PIX_FMT_BGR32 PIX_FMT_BGR32-#define AV_PIX_FMT_BGR32_1 PIX_FMT_BGR32_1-#define AV_PIX_FMT_RGB8 -1-#define AV_PIX_FMT_BGR8 -1-#define AV_PIX_FMT_RGB4_BYTE -1-#define AV_PIX_FMT_BGR4_BYTE -1-#define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8-#define AV_PIX_FMT_GRAY16 PIX_FMT_GRAY16-#define AV_PIX_FMT_GRAY8A -1-#define AV_PIX_FMT_RGB565 PIX_FMT_RGB565-#define AV_PIX_FMT_RGB555 PIX_FMT_RGB555-#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P-#define AV_PIX_FMT_YUV420P9 PIX_FMT_YUV420P9-#define AV_PIX_FMT_YUV420P10 PIX_FMT_YUV420P10-#define AV_PIX_FMT_YUV420P12 -1-#define AV_PIX_FMT_YUV422P12 -1-#define AV_PIX_FMT_YUV444P12 -1-#define AV_PIX_FMT_YUV420P14 -1-#define AV_PIX_FMT_YUV422P14 -1-#define AV_PIX_FMT_YUV444P14 -1-#define AV_PIX_FMT_YUV420P16 PIX_FMT_YUV420P16-#define AV_PIX_FMT_YUV422P16 PIX_FMT_YUV422P16-#define AV_PIX_FMT_YUV444P16 PIX_FMT_YUV444P16-#define AV_PIX_FMT_RGBA64 -1-#define AV_PIX_FMT_BGRA64 -1-#define AV_PIX_FMT_PAL8 PIX_FMT_PAL8--#define AV_CODEC_ID_H264 CODEC_ID_H264-#define AV_CODEC_ID_THEORA CODEC_ID_THEORA-#define AV_CODEC_ID_MPEG4 CODEC_ID_MPEG4-#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO-#define AV_CODEC_ID_GIF CODEC_ID_GIF-#define AV_CODEC_ID_AAC CODEC_ID_AAC-#define AV_CODEC_ID_MP3 CODEC_ID_MP3-#define AV_CODEC_ID_DTS CODEC_ID_DTS-#define AV_CODEC_ID_HEVC -1-#define AV_CODEC_ID_VC1 -1-#define AV_CODEC_ID_RAWVIDEO CODEC_ID_RAWVIDEO--#define FF_PROFILE_AAC_HE -1-#define FF_PROFILE_AAC_HE_V2 -1-#define FF_PROFILE_AAC_LD -1-#define FF_PROFILE_AAC_ELD -1-#define FF_PROFILE_MPEG2_AAC_LOW -1-#define FF_PROFILE_MPEG2_AAC_HE -1--#define AVIO_FLAG_DIRECT -1--#define AV_ROUND_PASS_MINMAX -1--#define CODEC_FLAG_UNALIGNED -1-#define CODEC_FLAG_OUTPUT_CORRUPT -1--#define AVFMT_ALLOW_FLUSH -1-#define AVFMT_TS_NONSTRICT -1