Как из wmv-файла вытащить длительность видео-фрагмента? Или, как вариант, как при помощи wmplayer узнать продолжительность проигрывания видео-фрагмента? Или где можно посмотреть документацию по структуре wmv-файлов?
Сделал небольшой пример с использованием DirectShow, нужный файл передается в параметре командной строки: Код (ASM): format PE console entry startup include 'win32ax.inc''.idata' import data readable library kernel,'KERNEL32.DLL',\ ole,'OLE32.DLL', \ msvcrt, 'msvcrt.dll', \ shell, 'shell32.dll' import kernel,\ ExitProcess,'ExitProcess', \ GetCommandLine, 'GetCommandLineW' import ole,\ CoInitialize,'CoInitialize',\ CoCreateInstance,'CoCreateInstance' import msvcrt, \ printf, 'printf' import shell, \ CommandLineToArgvW, 'CommandLineToArgvW' section '.text' code readable executable IID_IGraphBuilder GUID 56a868a9-0ad4-11ce-b03a-0020af0ba770 IID_IMediaSeeking GUID 36b73880-c2c8-11cf-8b46-00805f6cef60 CLSID_FilterGraph GUID E436EBB3-524F-11CE-9F53-0020AF0BA770 const_100ns dq 10000000.0 proc startup locals graphBuilder IGraphBuilder pSource IBaseFilter pPin IPin mediaSeeking IMediaSeeking sSource du "Source", 0 sOutput du "Output", 0 pFileName dd ? lDuration dq 0 argc dd 0 endl finit invoke CommandLineToArgvW, <invoke GetCommandLine>, addr argc .if ([argc] <> 2) cinvoke printf, "Usage: app.exe path_to_media" .else lea eax, [eax + 4] mov eax, [eax] mov [pFileName], eax invoke CoInitialize, NULL invoke CoCreateInstance, CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, addr graphBuilder .if (signed eax >= 0) cominvk graphBuilder, AddSourceFilter, [pFileName], addr sSource, addr pSource .if (signed eax >= 0) cominvk pSource, FindPin, addr sOutput, addr pPin .if (signed eax >= 0) cominvk graphBuilder, Render, [pPin] .if (signed eax >= 0) cominvk graphBuilder, QueryInterface, IID_IMediaSeeking, addr mediaSeeking .if (signed eax >= 0) cominvk mediaSeeking, GetDuration, addr lDuration .if (signed eax >= 0) fild [lDuration] fdiv [const_100ns] fstp [lDuration] cinvoke printf, "Duration: %f sec.", double [lDuration] .else cinvoke printf, "IMediaSeeking::GetDuration failed 0x%x", eax .endif cominvk mediaSeeking, Release .else cinvoke printf, "IGraphBuilder::QueryInterface failed 0x%x", eax .endif .else cinvoke printf, "IGraphBuilder::Render failed 0x%x", eax .endif cominvk pPin, Release .else cinvoke printf, "IBaseFilter::FindPin failed 0x%x", eax .endif cominvk pSource, Release .else cinvoke printf, "IGraphBuilder::AddSourceFilter failed 0x%x", eax .endif cominvk graphBuilder, Release .else cinvoke printf, "CoCreateInstance failed 0x%x", eax .endif .endif invoke ExitProcess, 0 ret endp Для перевода в часы/минуты/секунды можно использовать к примеру StrFromTimeInterval.
в wmv-файле на 66h от начала в qword длительность файла в 100 nSec, то есть для перевода в mSec это значение нужно разделить на 10000 Код (ASM): local lpcbData:dword local hFile:qword local szBuff[100h]:byte . . . . ;get the length of playing a wmv-file mov qword ptr [rsp+30h],0 ;hTemplateFile mov qword ptr [rsp+28h],FILE_ATTRIBUTE_ARCHIVE ;dwFlagsAndAttributes mov qword ptr [rsp+20h],OPEN_EXISTING ;dwCreationDisposition lea rcx,FileName ;lpFileName invoke CreateFile,,GENERIC_READ,\ ;dwDesiredAccess FILE_SHARE_READ or FILE_SHARE_WRITE,\;dwShareMode 0 ;lpSecurityAttributes mov hFile,rax;handle to file mov qword ptr [rsp+20h],0 lea r9,lpcbData lea rdx,szBuff invoke ReadFile,eax,,100h invoke CloseHandle,hFile mov rax,qword ptr szBuff[66h];duration in 100 nSec ;Duration in 100 nSec-units is divided by 10000 and get in duration in 1 mSec-units mov edx,3518437209;"magic number" mul edx shr edx,13 mov duration,rdx;in mSec реализация здесь