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 }