ffmpeg-tutorials (empty) → 0.2.1
raw patch · 4 files changed
+310/−0 lines, 4 filesdep +SDLdep +basedep +haskell98setup-changed
Dependencies added: SDL, base, haskell98, hs-ffmpeg
Files
- Setup.hs +5/−0
- ffmpeg-tutorials.cabal +25/−0
- src/tutorial01/Main.hs +137/−0
- src/tutorial02/Main.hs +143/−0
+ Setup.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++import Distribution.Simple++main = defaultMain
+ ffmpeg-tutorials.cabal view
@@ -0,0 +1,25 @@+name: ffmpeg-tutorials+version: 0.2.1+cabal-version: >= 1.6+license: BSD3+author: Vasyl Pasternak+synopsis: Tutorials on ffmpeg usage to play video/audio+maintainer: vasyl.pasternak@gmail.com+description: A set of tutorials with raising complexity+copyright: (c) 2009 Vasyl Pasternak+stability: alpha+category: Media++build-type: Simple++executable tutorial01+ main-is: tutorial01/Main.hs+ hs-source-dirs: src+ build-depends: base < 4, haskell98, hs-ffmpeg >= 0.2.1++executable tutorial02+ main-is: tutorial02/Main.hs+ hs-source-dirs: src+ build-depends: base < 4, haskell98, SDL, hs-ffmpeg >= 0.2.1++
+ src/tutorial01/Main.hs view
@@ -0,0 +1,137 @@+{-+ Testing the ffmpeg video decoding.++ Rewritten from the C code, from the FFMpeg tutorial + (http://www.dranger.com/ffmpeg/)+ + (c) 2009 Vasyl Pasternak+ -}++module Main (main) where++-- FFMpeg imports +import qualified Media.FFMpeg as FF+import qualified Media.FFMpeg.Scale as S++-- Common imports+import Data.Version+import System.Environment (getArgs, getProgName)+import Text.Printf (printf)+import Data.Maybe (fromJust)+import Data.IORef (newIORef, readIORef, modifyIORef)+import Control.Monad (when)+import System.IO -- (WriteMode, withBinaryFile, hPutStr, hPutBuf)++main :: IO ()+main = do+ getArgs >>= \args ->+ case args of+ filename:[] -> decodeFile filename+ otherwise -> getProgName >>= \pn -> + (putStrLn . unlines) + ["Usage: \n"+ ,printf "%s filename\n" pn+ ,"Where <filename> is the path to the video file"]+ ++-- The main rutine, do all work+decodeFile :: String -> IO ()+decodeFile filename = + FF.withFFMpeg $ do + -- Print FFMpeg version+ printf "FFMpeg library initialized\n" + printf "\tlibAVFormat version: %s\n" (showVersion FF.libAVFormatVersion)+ printf "\tlibAVCodec version: %s\n" (showVersion FF.libAVCodecVersion)++ -- Open file+ ctx <- FF.openInputFile filename+ FF.findStreamInfo ctx+ -- FF.dumpFormat ctx filename+ + printf "File: %s\n" filename++ -- Get all streams from file+ let streams = FF.getStreams ctx+ printf "Found %d streams\n" (length streams)++ -- Retrive video streams+ let videoStreams = filter (\(_,s) -> maybe False ((==FF.CodecTypeVideo) . FF.getCodecType) (FF.getCodecContext s)) $ zip [0..] streams++ if null videoStreams + then do + printf "No video streams found. Exiting...\n"+ else do+ let (streamIdx, videoStream) = head videoStreams+ printf "Extracting video information from stream %d\n" (streamIdx :: Int) + + -- Starting decoding video+ let codecContext = fromJust $ FF.getCodecContext videoStream+ let codecId = FF.getCodecId codecContext+ printf "Video codec is '%s'\n" (show codecId)++ (Just decoder) <- FF.findDecoder codecId+ FF.openCodec codecContext decoder++ let (width, height, pixfmt) = (FF.getVideoWidth codecContext, + FF.getVideoHeight codecContext,+ FF.getPixelFormat codecContext)++ printf "Video dimensions are %dx%d\n" width height++ printf "Video pixel format is %s\n" (show pixfmt)+++ frame <- FF.allocFrame+ frameRGB <- FF.allocFrame+ + pictureSize <- FF.pictureGetSize FF.PixFmtRgb24 width height+ + buffer <- FF.allocBuffer pictureSize+ + FF.pictureFill frameRGB buffer FF.PixFmtRgb24 width height++ packet <- FF.allocPacket++ -- Prepare resizer+ scaler <- S.getContext (width, height, pixfmt) + (width, height, FF.PixFmtRgb24) [S.SwsBicubic]++ -- use IORef to cound packets+ idxRef <- newIORef (0 :: Int)++ while (FF.readFrame ctx packet) $ + do+ when (streamIdx == FF.getStreamIndex packet) $+ do+ frameFinished <- FF.decodeVideo codecContext frame packet+ when frameFinished $ + do+ -- Rescale the picture++ S.scale scaler + (FF.getPictureSlice frame) (FF.getPictureStride frame)+ 0 height+ (FF.getPictureSlice frameRGB) (FF.getPictureStride frameRGB)++ idx <- readIORef idxRef+ modifyIORef idxRef (+1)+ printf "\rDecoded frame %05d" (idx)+ when ((idx `mod` 100) == 0) $ + writePPM (printf "frame%05d.ppm" idx) width height+ buffer pictureSize+ FF.cleanPacket packet++ printf "\n"+++-- While cycle implementation+while :: IO Bool -> IO () -> IO ()+while cond body = do+ c <- cond+ when c $ body >> while cond body++writePPM fname width height buff b = + withBinaryFile fname WriteMode $ \h -> do+ hPutStr h (printf "P6\n%d %d\n255\n" width height)+ FF.withBuffer buff $ \buff' -> + hPutBuf h buff' b
+ src/tutorial02/Main.hs view
@@ -0,0 +1,143 @@+{-+ Testing the ffmpeg video decoding.++ Rewritten from the C code, from the FFMpeg tutorial + (http://www.dranger.com/ffmpeg/)+ + (c) 2009 Vasyl Pasternak+ -}++module Main (main) where++-- FFMpeg+import qualified Media.FFMpeg as FF+import qualified Media.FFMpeg.Scale as S++-- Common+import Data.Version+import System.Environment (getArgs, getProgName)+import Text.Printf (printf)+import Data.Maybe (fromJust)+import Data.IORef (newIORef, readIORef, modifyIORef)+import Control.Monad (when)+import System.IO -- (WriteMode, withBinaryFile, hPutStr, hPutBuf)++-- SDL+import Graphics.UI.SDL as SDL++main :: IO ()+main = do+ getArgs >>= \args ->+ case args of+ filename:[] -> decodeFile filename+ otherwise -> getProgName >>= \pn -> + (putStrLn . unlines) + ["Usage: \n"+ ,printf "%s filename\n" pn+ ,"Where <filename> is the path to the video file"]+ ++-- The main rutine, do all work+decodeFile :: String -> IO ()+decodeFile filename = do+ SDL.init [InitTimer, InitAudio, InitVideo]+ FF.withFFMpeg $ do + -- Print FFMpeg version+ printf "FFMpeg library initialized\n" + printf "\tlibAVFormat version: %s\n" (showVersion FF.libAVFormatVersion)+ printf "\tlibAVCodec version: %s\n" (showVersion FF.libAVCodecVersion)++ -- Open file+ ctx <- FF.openInputFile filename+ FF.findStreamInfo ctx+ -- FF.dumpFormat ctx filename+ + printf "File: %s\n" filename++ -- Get all streams from file+ let streams = FF.getStreams ctx+ printf "Found %d streams\n" (length streams)++ -- Retrive video streams+ let videoStreams = filter (\(_,s) -> maybe False ((==FF.CodecTypeVideo) . FF.getCodecType) (FF.getCodecContext s)) $ zip [0..] streams++ if null videoStreams + then do + printf "No video streams found. Exiting...\n"+ else do+ let (streamIdx, videoStream) = head videoStreams+ printf "Extracting video information from stream %d\n" (streamIdx :: Int) + + -- Starting decoding video+ let codecContext = fromJust $ FF.getCodecContext videoStream+ let codecId = FF.getCodecId codecContext+ printf "Video codec is '%s'\n" (show codecId)++ (Just decoder) <- FF.findDecoder codecId+ FF.openCodec codecContext decoder++ let (width, height, pixfmt) = (FF.getVideoWidth codecContext, + FF.getVideoHeight codecContext,+ FF.getPixelFormat codecContext)++ printf "Video dimensions are %dx%d\n" width height+ printf "Video pixel format is %s\n" (show pixfmt)++ -- init primary SDL surface+ screen <- SDL.setVideoMode width height 0 []++ -- init output surface+ rgbSurface <- SDL.createRGBSurface [] width height 24+ 0x0000FF 0x00FF00 0xFF0000 0x000000++ frame <- FF.allocFrame+ frameRGB <- FF.allocFrame+ + surfacePixels <- SDL.surfaceGetPixels rgbSurface >>= FF.makeBuffer++ FF.pictureFill frameRGB surfacePixels FF.PixFmtRgb24 width height++ packet <- FF.allocPacket++ -- Prepare resizer+ scaler <- S.getContext (width, height, pixfmt) + (width, height, FF.PixFmtRgb24) [S.SwsBicubic]++ -- use IORef to cound packets+ idxRef <- newIORef (0 :: Int)++ while (FF.readFrame ctx packet) $ + do+ when (streamIdx == FF.getStreamIndex packet) $+ do+ frameFinished <- FF.decodeVideo codecContext frame packet+ when frameFinished $ + do+ -- Rescale the picture++ SDL.lockSurface rgbSurface++ S.scale scaler + (FF.getPictureSlice frame) (FF.getPictureStride frame)+ 0 height+ (FF.getPictureSlice frameRGB) (FF.getPictureStride frameRGB)++ -- show on screen + SDL.unlockSurface rgbSurface+ SDL.blitSurface rgbSurface Nothing screen Nothing+ SDL.flip screen++ idx <- readIORef idxRef+ modifyIORef idxRef (+1)+ printf "\rDecoded frame %05d" (idx)+ FF.cleanPacket packet++ printf "\n"+++-- While cycle implementation+while :: IO Bool -> IO () -> IO ()+while cond body = do+ c <- cond+ when c $ body >> while cond body+