-
Notifications
You must be signed in to change notification settings - Fork 1
/
Movie.pas
249 lines (216 loc) · 6.79 KB
/
Movie.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
unit Movie;
{$I Information.inc}
// basic review and reformatting: done
interface
uses
// Delphi
Winapi.MMSystem;
const
WMV_EXTENSIONS: array[0..1] of string = ('.wmv', '.asf');
AVI_EXTENSIONS: array[0..1] of string = ('.avi', '.divx');
MP4_EXTENSIONS: array[0..2] of string = ('.mp4', '.m4v', '.mp4v');
type
TMovieType = (mtUnknown, mtWMV, mtAVI, mtMP4, mtHQAVI, mtHDAVI, mtNone);
const
MovieTypeStr: array[TMovieType] of string = ('Unknown', 'WMV', 'AVI', 'MP4', 'HQ', 'HD', 'None');
type
TMovieInfo = class
private
FMovieType: TMovieType;
function GetFrameCount: Int64;
procedure SetMovieType(const Value: TMovieType);
procedure GetAviInformation;
public
// movie params
MovieLoaded: Boolean;
CanStepForward: Boolean;
FFourCC: FOURCC;
TimeFormat: TGUID;
ratio: Double;
nat_w, nat_h: Integer;
current_file_duration, frame_duration: Double;
frame_duration_source: Char;
current_filename, target_filename: string;
current_filesize: Int64;
property FrameCount: Int64 read GetFrameCount;
property MovieType: TMovieType read FMovieType write SetMovieType;
function FormatPosition(Position: Double): string; overload;
function FormatPosition(Position: Double; TimeFormat: TGUID): string; overload;
function FormatFrameRate: string;
function MovieTypeString: string;
function GetStringFromMovieType(aMovieType: TMovieType): string;
function InitMovie(FileName: string): Boolean;
end;
function FrameRateToStr(const frame_duration: Double; const frame_duration_source: Char): string;
implementation
uses
// Delphi
Winapi.Windows, Winapi.DirectShow9, System.SysUtils, System.StrUtils,
// Jedi
VfW,
// CA
CAResources, Utils;
function FrameRateToStr(const frame_duration: Double; const frame_duration_source: Char): string;
begin
if frame_duration <= 0 then
Result := CAResources.RsMovieFrameRateNotAvailable
else
Result := Format(CAResources.RsMovieFrameRateAvailable, [1.0 / frame_duration]);
if frame_duration_source <> #0 then
Result := Format(CAResources.RsMovieFrameRateSource, [Result, string(frame_duration_source)]);
end;
{ TMovieInfo }
function TMovieInfo.FormatFrameRate: string;
begin
if MovieLoaded then
Result := FrameRateToStr(frame_duration, frame_duration_source)
else
Result := FrameRateToStr(-1, '-');
end;
function TMovieInfo.GetFrameCount: Int64;
begin
Result := Trunc(current_file_duration / frame_duration);
end;
function TMovieInfo.InitMovie(FileName: string): Boolean;
function FileSize64: Int64;
var
R: TSearchRec;
begin
if FindFirst(FileName, faAnyFile, R) = 0 then
begin
Result := R.Size;
FindClose(R);
end else
Result := -1;
end;
const
BytesToRead = 32;
var
FileData: AnsiString;
s, file_ext: string;
f: file;
begin
Result := False;
if FileExists(FileName) then
begin
// determine filesize
AssignFile(f, FileName);
FileMode := fmOpenRead;
Reset(f, 1);
try
SetLength(FileData, BytesToRead);
current_filename := FileName;
// current_filesize := Filesize(f);
BlockRead(f, FileData[1], BytesToRead);
finally
CloseFile(f)
end;
current_filesize := FileSize64;
MovieType := mtUnknown;
frame_duration := 0;
frame_duration_source := '-';
FFourCC := 0;
Result := True;
// detect Avi file
if (Copy(FileData, 1, 4) = 'RIFF') and (Copy(FileData, 9, 4) = 'AVI ') then
MovieType := mtAVI;
// detect ISO file
if Copy(FileData, 5, 4) = 'ftyp' then
MovieType := mtMP4;
// for OTR
if (MovieType = mtUnknown) or (MovieType = mtAVI) then
if FileName.EndsWith('.hq.avi', True) then
MovieType := mtHQAVI
else
if FileName.EndsWith('.hd.avi', True) then
MovieType := mtHDAVI;
// try to detect MovieType from file extension
if MovieType = mtUnknown then
begin
file_ext := ExtractFileExt(FileName);
if AnsiMatchText(file_ext, WMV_EXTENSIONS) then
MovieType := mtWMV
else if AnsiMatchText(file_ext, AVI_EXTENSIONS) then
MovieType := mtAVI
else if AnsiMatchText(file_ext, MP4_EXTENSIONS) then
MovieType := mtMP4;
end;
// try to get Video FourCC from AVI
if MovieType in [mtAVI, mtHQAVI, mtHDAVI] then
begin
GetAviInformation;
if FFourCC <> 0 then
begin
s := fcc2String(FFourCC);
if SameText(s, 'DX50') then
MovieType := mtAVI
else
if SameText(s, 'H264') and (MovieType = mtAVI) then
MovieType := mtHQAVI;
end else
MovieType := mtUnknown;
end;
end;
end;
function TMovieInfo.FormatPosition(Position: Double): string;
begin
if isEqualGUID(TimeFormat, TIME_FORMAT_MEDIA_TIME) then
Result := secondsToTimeString(Position)
else
Result := format('%.0n', [Position]);
end;
function TMovieInfo.FormatPosition(Position: Double; TimeFormat: TGUID): string;
begin
if isEqualGUID(TimeFormat, TIME_FORMAT_MEDIA_TIME) then
Result := secondsToTimeString(Position)
else if IsEqualGUID(TimeFormat, TIME_FORMAT_FRAME) then
Result := format('%.0n', [Position])
else
Result := format('%n', [Position]);
end;
function TMovieInfo.GetStringFromMovieType(aMovieType: TMovieType): string;
begin
case aMovieType of
mtUnknown : Result := CAResources.RsMovieTypeUnknown;
mtWMV : Result := CAResources.RsMovieTypeWmf;
mtAVI : Result := CAResources.RsMovieTypeAvi;
mtMP4 : Result := CAResources.RsMovieTypeMp4;
mtHQAVI : Result := CAResources.RsMovieTypeHqAvi;
mtHDAVI : Result := CAResources.RsMovieTypeHdAvi;
else Result := CAResources.RsMovieTypeNone;
end;
end;
function TMovieInfo.MovieTypeString: string;
begin
Result := GetStringFromMovieType(FMovieType);
end;
procedure TMovieInfo.SetMovieType(const Value: TMovieType);
begin
FMovieType := Value;
end;
procedure TMovieInfo.GetAviInformation;
var
AVIStream: IAVIStream;
StreamInfo: TAVIStreamInfoW;
begin
AVIFileInit; // Init VfW API
try
if Succeeded(AVIStreamOpenFromFile(AVIStream, PChar(current_filename), streamtypeVIDEO, 0, OF_READ, nil)) then
begin
AVIStream.Info(StreamInfo, SizeOf(streamInfo));
FFourCC := StreamInfo.fccHandler;
if StreamInfo.dwRate <> 0 then
begin
frame_duration_source := 'A';
frame_duration := StreamInfo.dwScale / StreamInfo.dwRate;
end else
begin
frame_duration_source := 'a';
frame_duration := 0.04;
end;
end;
finally
AVIFileExit;
end;
end;
end.