unit info_get; //{$DEFINE _DEBUG} //{$DEFINE _BITMAP} interface uses Windows, Classes, DirectShow9, Graphics, myTag, myWStrings; type T_MyMediaInfo = class(TObject) private FiUniquID : Integer; FiPlaylistIndex : Integer; FsMediaTitle : WideString; FsMediaArtist : WideString; FsMediaAlbum : WideString; FiVideoWidth : Integer; FiVideoHeight : Integer; FfVideoFrameRate : Double; FfMediaDuration : TRefTime; FiMediaLength : Integer; FsFileName : WideString; FiFileSize : Int64; FiFileLastWriteTime : Int64; FiFileCreationTime : Int64; FsMediaLengthString : WideString; FsVideoFrameRateString : WideString; FsFileSizeString : WideString; FsFileLastWriteTimeString : WideString; FsFileCreationTimeString : WideString; {$IFDEF _BITMAP} FThumbImage : TBitmap; {$ENDIF} procedure FSetPlaylistIndex(iIndex: Integer); function FGetFileTimeInt(ATime: TFileTime): Int64; function FGetMediaTitle: WideString; public constructor Create; overload; constructor Create(sFileName: WideString); overload; constructor Create(sFileName: WideString; AFindData: TWin32FindDataW); overload; destructor Destroy; override; procedure Assign(AMediaInfo: T_MyMediaInfo); procedure _SetUniquID(iIndex: Integer); procedure _SetFileName(sFileName: WideString); procedure _SetFileLastWriteTime(ATime: TFileTime); procedure _SetTag(ATag: TMyTag); procedure _SetVideoSize(AVideoSize: TMyVideoSize); {$IFDEF _BITMAP} procedure _SetThumbImage(ABitmap: TBitmap); {$ENDIF} function MediaHasImage: Boolean; property PlaylistIndex : Integer read FiPlaylistIndex write FSetPlaylistIndex; property UniquID : Integer read FiUniquID; property FileName : WideString read FsFileName; property FileSize : Int64 read FiFileSize; property FileCreationTime : Int64 read FiFileCreationTime; property FileLastWriteTime : Int64 read FiFileLastWriteTime; property MediaDuration : TRefTime read FfMediaDuration; property MediaLength : Integer read FiMediaLength; property MediaRawTitle : WideString read FsMediaTitle; property MediaTitle : WideString read FGetMediaTitle; property MediaArtist : WideString read FsMediaArtist; property MediaAlbum : WideString read FsMediaAlbum; property VideoWidth : Integer read FiVideoWidth; property VideoHeight : Integer read FiVideoHeight; property VideoFrameRate : Double read FfVideoFrameRate; property MediaLengthString : WideString read FsMediaLengthString; property VideoFrameRateString : WideString read FsVideoFrameRateString; property FileSizeString : WideString read FsFileSizeString; property FileLastWriteTimeString : WideString read FsFileLastWriteTimeString; property FileCreationTimeString : WideString read FsFileCreationTimeString; {$IFDEF _BITMAP} property Bitmap : TBitmap read FThumbImage; {$ENDIF} end; type T_MyInfoGet = class(TThread) private { Private 宣言 } FiIndex : Integer; FsFileName : WideString; FMediaInfo : T_MyMediaInfo; FbCreateTag : Boolean; FbUpdateVideoSize : Boolean; {$IFDEF _BITMAP} FbUpdateThumbImage : Boolean; procedure UpdateInfo3; {$ENDIF} function IsTerminated: Boolean; procedure UpdateInfo; procedure UpdateInfo2; protected procedure Execute; override; public constructor Create(iIndex: Integer; AStrings: TMyWStrings); destructor Destroy; override; end; //var // G_PlaylistStrings : TMyWStrings; implementation uses {$IFDEF _DEBUG} myDebug, {$ENDIF} Forms, SysUtils, myDShow, myFile, myGraphic, myNum, main; //------------------------------------------------------------------------------ { T_MyMediaInfo } constructor T_MyMediaInfo.Create; begin inherited Create; //ファイル名 FsFileName := ''; FiFileSize := 0; FiFileLastWriteTime := 0; FiFileCreationTime := 0; FsFileSizeString := ''; FsFileLastWriteTimeString := ''; FsFileCreationTimeString := ''; FiUniquID := -1; FiPlaylistIndex := -1; FsMediaTitle := ''; FsMediaArtist := ''; FsMediaAlbum := ''; FiVideoWidth := 0; FiVideoHeight := 0; FfVideoFrameRate := 0; FfMediaDuration := 0; FiMediaLength := 0; FsMediaLengthString := ''; FsVideoFrameRateString := ''; {$IFDEF _BITMAP} FThumbImage := nil; {$ENDIF} end; function _GetFileSizeString(iFileSize: Int64): String; begin if (iFileSize >= (1024 * 1024 * 1024)) then begin //GByte Result := Format('%.2fGB', [gfniRoundDown((gfniRoundUp(iFileSize / 1024) / (1024 * 1024)) * 100) / 100]); end else if (iFileSize >= (1024 * 1024)) then begin //MByte Result := Format('%.1fMB', [gfniRoundDown((gfniRoundUp(iFileSize / 1024) / 1024) * 10) / 10]); end else if (iFileSize >= 1024) then begin //KByte Result := Format('%dKB', [gfniRoundUp(iFileSize / 1024)]); end else begin //Byte Result := Format('%dB', [iFileSize]); end; end; constructor T_MyMediaInfo.Create(sFileName : WideString; AFindData : TWin32FindDataW); begin //ファイル名 Self.Create; FsFileName := sFileName; FiFileSize := AFindData.nFileSizeHigh * (Int64(MAXDWORD) +1) + AFindData.nFileSizeLow; FiFileLastWriteTime := FGetFileTimeInt(AFindData.ftLastWriteTime); FiFileCreationTime := FGetFileTimeInt(AFindData.ftCreationTime); FsFileSizeString := _GetFileSizeString(FiFileSize); FsFileLastWriteTimeString := gfnsFileTimeStringGet(AFindData.ftLastWriteTime); FsFileCreationTimeString := gfnsFileTimeStringGet(AFindData.ftCreationTime); end; constructor T_MyMediaInfo.Create(sFileName: WideString); var lh_File : THandle; l_FindData : TWin32FindDataW; begin //ファイル名 FsFileName := sFileName; lh_File := FindFirstFileW(PWideChar(sFileName), l_FindData); try if (lh_File <> INVALID_HANDLE_VALUE) then begin { FiFileSize := l_FindData.nFileSizeHigh * (Int64(MAXDWORD) +1) + l_FindData.nFileSizeLow; FiFileLastWriteTime := FGetFileTimeInt(l_FindData.ftLastWriteTime); FiFileCreationTime := FGetFileTimeInt(l_FindData.ftCreationTime); FsFileSizeString := _GetFileSizeString(FiFileSize); FsFileLastWriteTimeString := gfnsFileTimeStringGet(l_FindData.ftLastWriteTime); FsFileCreationTimeString := gfnsFileTimeStringGet(l_FindData.ftCreationTime); } Self.Create(sFileName, l_FindData); end else begin Self.Create; end; finally Windows.FindClose(lh_File); end; end; destructor T_MyMediaInfo.Destroy; begin {$IFDEF _BITMAP} FreeAndNil(FThumbImage); {$ENDIF} inherited Destroy; end; procedure T_MyMediaInfo.Assign(AMediaInfo: T_MyMediaInfo); begin FsFileName := AMediaInfo.FileName; FiFileSize := AMediaInfo.FileSize; FiFileLastWriteTime := AMediaInfo.FileLastWriteTime; FiFileCreationTime := AMediaInfo.FileCreationTime; FsFileSizeString := AMediaInfo.FileSizeString; FsFileLastWriteTimeString := AMediaInfo.FileLastWriteTimeString; FsFileCreationTimeString := AMediaInfo.FileCreationTimeString; FiUniquID := AMediaInfo.UniquID; FiPlaylistIndex := AMediaInfo.PlaylistIndex; FsMediaTitle := AMediaInfo.MediaTitle; FsMediaArtist := AMediaInfo.MediaArtist; FsMediaAlbum := AMediaInfo.MediaAlbum; FiVideoWidth := AMediaInfo.VideoWidth; FiVideoHeight := AMediaInfo.VideoHeight; FfVideoFrameRate := AMediaInfo.VideoFrameRate; FfMediaDuration := AMediaInfo.MediaDuration; FiMediaLength := AMediaInfo.MediaLength; FsMediaLengthString := AMediaInfo.MediaLengthString; FsVideoFrameRateString := AMediaInfo.VideoFrameRateString; {$IFDEF _BITMAP} if (AMediaInfo.MediaHasImage) then begin _SetThumbImage(AMediaInfo.Bitmap); end else begin FreeAndNil(FThumbImage); end; {$ENDIF} end; function T_MyMediaInfo.FGetFileTimeInt(ATime: TFileTime): Int64; begin Result := ATime.dwHighDateTime * (Int64(MAXDWORD) +1) + ATime.dwLowDateTime; end; procedure T_MyMediaInfo.FSetPlaylistIndex(iIndex: Integer); begin FiPlaylistIndex := iIndex; end; procedure T_MyMediaInfo._SetUniquID(iIndex: Integer); begin FiUniquID := iIndex; end; procedure T_MyMediaInfo._SetFileName(sFileName: WideString); begin FsFileName := sFileName; end; procedure T_MyMediaInfo._SetFileLastWriteTime(ATime: TFileTime); begin FiFileLastWriteTime := FGetFileTimeInt(ATime); FsFileLastWriteTimeString := gfnsFileTimeStringGet(ATime); end; procedure T_MyMediaInfo._SetVideoSize(AVideoSize: TMyVideoSize); begin FiVideoWidth := AVideoSize.Width; FiVideoHeight := AVideoSize.Height; FfMediaDuration := AVideoSize.Duration; FiMediaLength := gfniRound(FfMediaDuration); FfVideoFrameRate := AVideoSize.VideoFrameRate;; if (FiMediaLength > 0) then begin FsMediaLengthString := gfnsSecToTimeStr(FiMediaLength); end else begin FsMediaLengthString := '-'; end; if (FfVideoFrameRate = 0) then begin FsVideoFrameRateString := '-'; end else begin FsVideoFrameRateString := Format('%g', [gfniRound(100 / FfVideoFrameRate) / 100]); end; end; function T_MyMediaInfo.FGetMediaTitle: WideString; begin if (FsMediaTitle = '') then begin Result := gfnsFileMainGet(FsFileName); end else begin Result := FsMediaTitle; end; end; procedure T_MyMediaInfo._SetTag(ATag: TMyTag); begin FsMediaTitle := ATag.Title; FsMediaArtist := ATag.Artist; FsMediaAlbum := ATag.Album; end; {$IFDEF _BITMAP} procedure T_MyMediaInfo._SetThumbImage(ABitmap: TBitmap); begin if (FThumbImage = nil) then begin FThumbImage := TBitmap.Create; with FThumbImage do begin Width := 64; Height := 64; Canvas.Brush.Color := clBlack; end; end; FThumbImage.Canvas.FillRect(Rect(0, 0, FThumbImage.Width, FThumbImage.Height)); if (ABitmap = nil) or (ABitmap.Width <= 0) or (ABitmap.Height <= 0) then begin Exit; end; gpcBmpCopy(ABitmap, FThumbImage); end; {$ENDIF} function T_MyMediaInfo.MediaHasImage: Boolean; begin Result := {$IFDEF _BITMAP} (FThumbImage <> nil) and {$ENDIF} (FiVideoWidth > 0) and (FiVideoHeight > 0) // and (FThumbImage.Width > 0) // and (FThumbImage.Height > 0) ; end; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ { T_MyInfoGet } constructor T_MyInfoGet.Create(iIndex: Integer; AStrings: TMyWStrings); var l_MediaInfo : T_MyMediaInfo; li_Time1 : Int64; li_Time2 : Int64; begin FiIndex := iIndex; FsFileName := AStrings[iIndex]; FMediaInfo := nil; FbCreateTag := True; FbUpdateVideoSize := True; {$IFDEF _BITMAP} FbUpdateThumbImage := True; {$ENDIF} try if not(FileExists(FsFileName)) then begin Exit; end else begin if (AStrings.Objects[iIndex] = nil) //Objectsはnilではないはずである then begin //ここにはこないはず FMediaInfo := T_MyMediaInfo.Create(FsFileName); end else begin //オブジェクト作成済み { if not(AStrings.Objects[iIndex] is T_MyMediaInfo) then begin Beep; Exit; end; } l_MediaInfo := T_MyMediaInfo(AStrings.Objects[iIndex]); if (gfnbIsEqualFileName(l_MediaInfo.FileName, FsFileName)) then begin //ファイル名が一致 if (l_MediaInfo.MediaRawTitle = '') then begin //タグ未取得 //タグを取得しなければならない //ビデオのサイズや長さは取得済みか if (l_MediaInfo.MediaDuration > 0) then begin FbUpdateVideoSize := False; end; {$IFDEF _BITMAP} //サムネイルイメージを取得済みか if (l_MediaInfo.MediaHasImage) then begin FbUpdateThumbImage := False; end; {$ENDIF} end else begin //タグ取得済み li_Time1 := l_MediaInfo.FileLastWriteTime; li_Time2 := gfniFileLastWriteTimeGet(FsFileName); if (li_Time1 <> li_Time2) then begin //取得時の更新日時と現在の更新日時が違うのでタグを取得し直さなければならない end else begin //取得済みのタグ情報の更新日と現在の更新日が同じならタグ情報の更新の必要はない FbCreateTag := False; if (l_MediaInfo.MediaDuration < 0.001) then begin //だがしかし長さが0ならビデオサイズの取得などはまだなのでビデオサイズの更新は行う end else begin FbUpdateVideoSize := False; //Exit; end; {$IFDEF _BITMAP} if not(l_MediaInfo.MediaHasImage) then begin //だがしかし長さが0ならビデオサイズの取得などはまだなのでビデオサイズの更新は行う end else begin FbUpdateThumbImage := False; end; {$ENDIF} if (FbUpdateVideoSize = False) {$IFDEF _BITMAP} and (FbUpdateThumbImage = False) {$ENDIF} then begin //すべての更新の必要なし Exit; end; end; end; end; FMediaInfo := T_MyMediaInfo.Create; FMediaInfo.Assign(l_MediaInfo); end; end; finally {$IFDEF _DEBUG} myDebug.gpcDebug('InfoGet Create'); {$ENDIF} FreeOnTerminate := True; // FreeOnTerminate := False; inherited Create(False); end; end; destructor T_MyInfoGet.Destroy; begin {$IFDEF _DEBUG} myDebug.gpcDebug(['InfoGet Destroy', FbCreateTag, FbUpdateVideoSize]); {$ENDIF} // FreeAndNil(FMediaInfo); if (FMediaInfo <> nil) then begin FMediaInfo.Free; end; inherited; end; function T_MyInfoGet.IsTerminated: Boolean; begin Result := (Terminated) or (Application.Terminated); end; procedure T_MyInfoGet.Execute; var l_Tag : TMyTag; l_VideoSize : TMyVideoSize; // l_Bitmap : TBitmap; begin {$IFDEF _DEBUG} myDebug.gpcDebug('InfoGet Execute'); {$ENDIF} if (IsTerminated) then begin Exit; end; if (FbCreateTag = False) and (FbUpdateVideoSize = False) {$IFDEF _BITMAP} and (FbUpdateThumbImage = False) {$ENDIF} then begin Synchronize(UpdateInfo); Synchronize(UpdateInfo2); {$IFDEF _BITMAP} Synchronize(UpdateInfo3); {$ENDIF} Exit; end; if (IsTerminated) then begin Exit; end; // FMediaInfo := T_MyMediaInfo.Create(FsFileName); // FMediaInfo._SetID(FiIndex); if (FbCreateTag) then begin //アーティスト名、タイトルなどのタグ情報 l_Tag := nil; try l_Tag := TMyTag.Create(FsFileName); FMediaInfo._SetTag(l_Tag); finally FreeAndNil(l_Tag); end; end; Synchronize(UpdateInfo); if (IsTerminated) then begin Exit; end; if (FbUpdateVideoSize) then begin //処理に時間がかかるので↑とは分けて取得。 //メディアの長さ、ビデオの大きさ、フレームレート。 l_VideoSize := gfnVideoSizeGet2(FsFileName); FMediaInfo._SetVideoSize(l_VideoSize); end; Synchronize(UpdateInfo2); if (IsTerminated) then begin Exit; end; //Exit; {$IFDEF _BITMAP} if (FbUpdateThumbImage) and (FMediaInfo.VideoWidth > 0) and (FMediaInfo.VideoHeight > 0) then begin //処理に時間がかかるので↑とは分けて取得。 l_Bitmap := nil; try l_Bitmap := TBitmap.Create; //メディアのサムネイルを取得 // gfnbBmpFromMedia(l_Bitmap, FsFileName, 5000); //5秒 gfnbBmpFromMediaVid(l_Bitmap, FsFileName, 10000, vmVideoRenderer); //10秒 FMediaInfo._SetThumbImage(l_Bitmap); finally FreeAndNil(l_Bitmap); end; end; Synchronize(UpdateInfo3); {$ENDIF} end; procedure T_MyInfoGet.UpdateInfo; begin {$IFDEF _DEBUG} myDebug.gpcDebug('UpdateInfo'); {$ENDIF} if (IsTerminated) then begin {$IFDEF _DEBUG} myDebug.gpcDebug('UpdateInfo Terminated'); {$ENDIF} Exit; end; G_InfoForm.SetInfo(Self, FiIndex, FMediaInfo); end; procedure T_MyInfoGet.UpdateInfo2; begin {$IFDEF _DEBUG} myDebug.gpcDebug('UpdateInfo2'); {$ENDIF} if (IsTerminated) then begin {$IFDEF _DEBUG} myDebug.gpcDebug('UpdateInfo2 Terminated'); {$ENDIF} Exit; end; G_InfoForm.SetInfo2(Self, FiIndex, FMediaInfo); end; {$IFDEF _BITMAP} procedure T_MyInfoGet.UpdateInfo3; begin {$IFDEF _DEBUG} myDebug.gpcDebug('UpdateInfo2'); {$ENDIF} if (IsTerminated) then begin {$IFDEF _DEBUG} myDebug.gpcDebug('UpdateInfo2 Terminated'); {$ENDIF} Exit; end; G_InfoForm.SetInfo3(Self, FiIndex, FMediaInfo); end; {$ENDIF} end.