1 // Written in the D programming language. 2 /++ 3 + Authors: KanzakiKino 4 + Copyright: KanzakiKino 2018 5 + License: LGPL-3.0 6 + 7 + This module declares utilities related to media file. 8 ++/ 9 module g4d.file.media; 10 import g4d.util.bitmap, 11 g4d.exception; 12 import easyff.api; 13 import gl3n.linalg; 14 import std.conv, 15 std..string; 16 17 /// 18 class EasyFFException : G4dException 19 { 20 /// 21 this ( FFError err, string file = __FILE__, size_t line = __LINE__ ) 22 { 23 super( err.to!string, file, line ); 24 } 25 } 26 27 /// A class that decodes media file. 28 class MediaFile 29 { 30 protected FFReader* _file; 31 protected FFStream* _video; 32 33 /// 34 this ( string path ) 35 { 36 _file = FFReader_new( path.toStringz ); 37 _video = FFReader_findVideoStream( _file ); 38 39 auto ret = FFReader_checkError( _file ); 40 if ( ret == FFError.NoError && _video ) { 41 ret = FFStream_checkError( _video ); 42 } 43 if ( ret != FFError.NoError ) { 44 throw new EasyFFException( ret ); 45 } 46 } 47 48 /// 49 ~this () 50 { 51 dispose(); 52 } 53 /// Releases all ffmpeg contexts. 54 void dispose () 55 { 56 if ( _file ) { 57 FFReader_delete( &_file ); 58 _file = null; 59 } 60 _video = null; 61 } 62 63 /// Checks if the media file has video/image stream. 64 const @property hasVideoStream () { return !!_video; } 65 66 /// Decodes and returns next image as RGBA bitmap. 67 BitmapRGBA decodeNextImage () 68 { 69 if ( !hasVideoStream ) { 70 throw new G4dException( "Video stream is not found." ); 71 } 72 FFReader_decode( _file, _video ); 73 74 auto image = FFReader_convertFrameToImage( _file ); 75 if ( !image ) { 76 throw new G4dException( "Converting frame to image is failed." ); 77 } 78 scope(exit) FFImage_delete( &image ); 79 80 const w = FFImage_getWidth ( image ); 81 const h = FFImage_getHeight( image ); 82 auto buf = FFImage_getBuffer( image ); 83 return new BitmapRGBA( vec2i(w,h), buf ); 84 } 85 }