file - 从 avi 文件中提取正确的创建日期
问题描述
我正在使用 Delphi 10 和 Windows 10 Home Edition 64 位。我有一个名为 MVI_0640.AVI 的视频文件。文件资源管理器中显示的日期是 15/04/04,对应于“属性”窗口中的媒体创建日期。
我正在使用以下代码来提取日期。
procedure TForm1.Button1Click(Sender: TObject);
var
ADate: TDateTime;
FlHandle: integer;
MyData: TWin32FindData;
FlTime: TFileTime;
MySysTime: TSystemTime;
begin
{get date using GetCreationTime}
ADate := TFile.GetCreationTime(FlName);
Memo1.Lines.Add('GetCreationTime ' + DateToStr(ADate));
{get date using FileGetDate}
FlHandle := FileOpen(FlName,fmOpenRead);
ADate := FileDateToDateTime(FileGetDate(FlHandle));
FileClose(FlHandle);
Memo1.Lines.Add('FileGetDate ' + DateToStr(ADate));
{get date using FindFirstFile}
FindFirstFile(PChar(FlName), MyData);
FlTime := MyData.ftCreationTime;
FileTimeToSystemTime(FlTime, MySysTime);
ADate := SystemTimeToDateTime(MySysTime);
Memo1.Lines.Add('ftCreationTime ' + DateToStr(ADate));
FlTime := MyData.ftLastAccessTime;
FileTimeToSystemTime(FlTime, MySysTime);
ADate := SystemTimeToDateTime(MySysTime);
Memo1.Lines.Add('ftLastAccessTime ' + DateToStr(ADate));
FlTime := MyData.ftLastWriteTime;
FileTimeToSystemTime(FlTime, MySysTime);
ADate := SystemTimeToDateTime(MySysTime);
Memo1.Lines.Add('ftLastWriteTime ' + DateToStr(ADate));
end;
结果如下所示:
没有任何日期反映媒体创建日期。我怎样才能提取它?
解决方案
您要查找的日期位于名为IDIT
. 例如,在本文档中提及
结构很简单,(我的文件中的示例数据):
chunk id: IDIT // 4 ASCII chars
chunk length: 0000001A // 26 bytes
chunk data: Sun Aug 31 12:15:22 2008/n/0 // date as ascii string
Microsoft 概述AVI
了文件的结构,如下所示,并添加了 IDIT 块的位置(如果存在)
RIFF ('AVI '
LIST ('hdrl'
'avih'(<Main AVI Header>)
LIST ('strl'
'strh'(<Stream header>)
'strf'(<Stream format>)
[ 'strd'(<Additional header data>) ]
[ 'strn'(<Stream name>) ]
...
)
... (note, if present, the IDIT chunk appears here)
)
LIST ('movi'
{SubChunk | LIST ('rec '
SubChunk1
SubChunk2
...
)
...
}
...
)
['idx1' (<AVI Index>) ]
)
上述文件还概述了各种结构。
获取日期(如果文件中存在)的函数可能如下所示:
// Note! finetuned to search only the main TLIST 'hdrl'
function GetOriginalDate(AviFileName: TFileName; out s: string): boolean;
type
TChunkId = array[0..3] of AnsiChar;
TChunk = record
chid: TChunkId;
size: cardinal;
form: TChunkId;
end;
var
fs: TFileStream;
Root: TChunk;
Chnk: TChunk;
Done: boolean;
Date: ansistring;
endpos: integer;
begin
s := 'not found';
Done := False;
result := False;
fs:= TFileStream.Create(AviFileName, fmOpenRead or fmShareDenyWrite);
try
fs.Read(Root, SizeOf(Root));
if Root.chid <> 'RIFF' then exit;
if Root.form <> 'AVI ' then exit;
fs.Read(Chnk, SizeOf(TChunk)); // main LIST
if Chnk.chid <> 'LIST' then exit;
if Chnk.form <> 'hdrl' then exit;
endpos := fs.Position + Chnk.size;
repeat
fs.Read(Chnk, SizeOf(TChunk));
if Chnk.chid = 'IDIT' then
begin
fs.Seek(-4, TSeekOrigin.soCurrent);
SetLength(Date, Chnk.size);
fs.Read(Date[1], Length(Date));
s := Date;
Done := True;
end
else
fs.Seek(Chnk.size-4, TSeekOrigin.soCurrent);
until Done or (fs.Position > endpos);
finally
fs.Free;
end;
end;
调用它,例如:
procedure TForm1.Button2Click(Sender: TObject);
var
s: string;
begin
GetOriginalDate('F:\My Video\2008-08-31\MVI_1279.AVI', s);
Memo1.Lines.Add(s);
end;
结果是Memo1
Sun Aug 31 12:15:22 2008
推荐阅读
- architecture - 数据湖不变性规则的例外情况
- google-maps - 使用 Google Map API 在 App 中获取路线导航
- javascript - Axios DELETE 请求中的重定向承诺使用 DELETE 而不是 GET
- swift - 重新分配期间的 Swift 内存 Deinit
- java - 用户可以编辑android资源文件吗?访问所有类的字符串
- c# - ASP.NET Core 3.1 日期发布本地化问题
- kdb - 从 kdb 中的 TP 重放日志文件时,RDB 和 TP 之间的消息数差异
- r - 来自不同包的具有相同名称的 R S4 类
- javascript - 如何从module.exports.x lamba serverless主体中的github url获取数据json?
- git - Git 在合并到 master 时忽略分支上的更改