Blog. Just Blog

Мультимедийный плеер на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Мультимедийный плеер на Ассемблере
Мультимедийный плеер на Ассемблере

Сегодня будем программировать нечто действительно интересное, а именно универсальный мультимедийный плеер. Универсальность реализуется мощью функционала DirectShow, а также установленными в системе аудио- и видеокодеками. И пусть это не полноценное приложение, большинство основных функций плеера в нем будут реализованы.

Сперва, как обычно, нам понадобится здоровенная пачка различных GUID'ов, интерфейсов и констант. Значение CLSID_FilterGraph почему-то даже не описано в SDK, пришлось покопаться в интернетах.
  1. ; GUID {E436EBB3-524F-11CE-9F53-0020AF0BA770}
  2. CLSID_FilterGraph \
  3.     dd 0E436EBB3h
  4.     dw 0524Fh
  5.     dw 011CEh
  6.     db 09Fh, 053h, 000h, 020h, 0AFh, 00Bh, 0A7h, 070h
  7.  
  8. ; GUID {56A868A9-0AD4-11CE-B03A-0020AF0BA770}
  9. IID_IGraphBuilder \
  10.     dd 056A868A9h
  11.     dw 00AD4h
  12.     dw 011CEh
  13.     db 0B0h, 03Ah, 000h, 020h, 0AFh, 00Bh, 0A7h, 070h
  14.  
  15. ; IID_IGraphBuilder Interface
  16. struct IGraphBuilder
  17.     ; IUnknown
  18.     QueryInterface          dd ?   ; 000h
  19.     AddRef                  dd ?   ; 004h
  20.     Release                 dd ?   ; 008h
  21.     ; IGraphBuilder
  22.     AddFilter               dd ?   ; 00Ch
  23.     RemoveFilter            dd ?   ; 010h
  24.     EnumFilters             dd ?   ; 014h
  25.     FindFilterByName        dd ?   ; 018h
  26.     ConnectDirect           dd ?   ; 01Ch
  27.     Reconnect               dd ?   ; 020h
  28.     Disconnect              dd ?   ; 024h
  29.     SetDefaultSyncSource    dd ?   ; 028h
  30.     Connect                 dd ?   ; 02Ch
  31.     Render                  dd ?   ; 030h
  32.     RenderFile              dd ?   ; 034h
  33.     AddSourceFilter         dd ?   ; 038h
  34.     SetLogFile              dd ?   ; 03Ch
  35.     Abort                   dd ?   ; 040h
  36.     ShouldOperationContinue dd ?   ; 044h
  37. ends
  38.  
  39. ; GUID {56A868B1-0AD4-11CE-B03A-0020AF0BA770}
  40. IID_IMediaControl \
  41.     dd 056A868B1h
  42.     dw 00AD4h
  43.     dw 011CEh
  44.     db 0B0h, 03Ah, 000h, 020h, 0AFh, 00Bh, 0A7h, 070h
  45.  
  46. ; IID_IMediaControl Interface
  47. struct IMediaControl
  48.     ; IUnknown
  49.     QueryInterface          dd ?   ; 000h
  50.     AddRef                  dd ?   ; 004h
  51.     Release                 dd ?   ; 008h
  52.     ; IMediaControl
  53.     GetTypeInfoCount        dd ?   ; 00Ch
  54.     GetTypeInfo             dd ?   ; 010h
  55.     GetIDsOfNames           dd ?   ; 014h
  56.     _Invoke                 dd ?   ; 018h
  57.     Run                     dd ?   ; 01Ch
  58.     Pause                   dd ?   ; 020h
  59.     Stop                    dd ?   ; 024h
  60.     GetState                dd ?   ; 028h
  61.     RenderFile              dd ?   ; 02Ch
  62.     AddSourceFilter         dd ?   ; 030h
  63.     get_FilterCollection    dd ?   ; 034h
  64.     get_RegFilterCollection dd ?   ; 038h
  65.     StopWhenReady           dd ?   ; 03Ch
  66. ends
  67.  
  68. ; GUID {56A868B4-0AD4-11CE-B03A-0020AF0BA770}
  69. IID_IVideoWindow \
  70.     dd 056A868B4h
  71.     dw 00AD4h
  72.     dw 011CEh
  73.     db 0B0h, 03Ah, 000h, 020h, 0AFh, 00Bh, 0A7h, 070h
  74.  
  75. ; IID_IVideoWindow Interface
  76. struct IVideoWindow
  77.     ; IUnknown
  78.     QueryInterface        dd ?   ; 000h
  79.     AddRef                dd ?   ; 004h
  80.     Release               dd ?   ; 008h
  81.     ; IVideoWindow
  82.     GetTypeInfoCount      dd ?   ; 00Ch
  83.     GetTypeInfo           dd ?   ; 010h
  84.     GetIDsOfNames         dd ?   ; 014h
  85.     _Invoke               dd ?   ; 018h
  86.     put_Caption           dd ?   ; 01Ch
  87.     get_Caption           dd ?   ; 020h
  88.     put_WindowStyle       dd ?   ; 024h
  89.     get_WindowStyle       dd ?   ; 028h
  90.     put_WindowStyleEx     dd ?   ; 02Ch
  91.     get_WindowStyleEx     dd ?   ; 030h
  92.     put_AutoShow          dd ?   ; 034h
  93.     get_AutoShow          dd ?   ; 038h
  94.     put_WindowState       dd ?   ; 03Ch
  95.     get_WindowState       dd ?   ; 040h
  96.     put_BackgroundPalette dd ?   ; 044h
  97.     get_BackgroundPalette dd ?   ; 048h
  98.     put_Visible           dd ?   ; 04Ch
  99.     get_Visible           dd ?   ; 050h
  100.     put_Left              dd ?   ; 054h
  101.     get_Left              dd ?   ; 058h
  102.     put_Width             dd ?   ; 05Ch
  103.     get_Width             dd ?   ; 060h
  104.     put_Top               dd ?   ; 064h
  105.     get_Top               dd ?   ; 068h
  106.     put_Height            dd ?   ; 06Ch
  107.     get_Height            dd ?   ; 070h
  108.     put_Owner             dd ?   ; 074h
  109.     get_Owner             dd ?   ; 078h
  110.     put_MessageDrain      dd ?   ; 07Ch
  111.     get_MessageDrain      dd ?   ; 080h
  112.     get_BorderColor       dd ?   ; 084h
  113.     put_BorderColor       dd ?   ; 088h
  114.     get_FullScreenMode    dd ?   ; 08Ch
  115.     put_FullScreenMode    dd ?   ; 090h
  116.     SetWindowForeground   dd ?   ; 094h
  117.     NotifyOwnerMessage    dd ?   ; 098h
  118.     SetWindowPosition     dd ?   ; 09Ch
  119.     GetWindowPosition     dd ?   ; 0A0h
  120.     GetMinIdealImageSize  dd ?   ; 0A4h
  121.     GetMaxIdealImageSize  dd ?   ; 0A8h
  122.     GetRestorePosition    dd ?   ; 0ACh
  123.     HideCursor            dd ?   ; 0B0h
  124.     IsCursorHidden        dd ?   ; 0B4h
  125. ends
  126.  
  127. ; GUID {36B73880-C2C8-11CF-8B46-00805F6CEF60}
  128. IID_IMediaSeeking \
  129.     dd 036B73880h
  130.     dw 0C2C8h
  131.     dw 011CFh
  132.     db 08Bh, 046h, 000h, 080h, 05Fh, 06Ch, 0EFh, 060h
  133.  
  134. ; IID_IMediaSeeking Interface
  135. struct IMediaSeeking
  136.     ; IUnknown
  137.     QueryInterface       dd ?   ; 000h
  138.     AddRef               dd ?   ; 004h
  139.     Release              dd ?   ; 008h
  140.     ; IMediaSeeking
  141.     GetCapabilities      dd ?   ; 00Ch
  142.     CheckCapabilities    dd ?   ; 010h
  143.     IsFormatSupported    dd ?   ; 014h
  144.     QueryPreferredFormat dd ?   ; 018h
  145.     GetTimeFormat        dd ?   ; 01Ch
  146.     IsUsingTimeFormat    dd ?   ; 020h
  147.     SetTimeFormat        dd ?   ; 024h
  148.     GetDuration          dd ?   ; 028h
  149.     GetStopPosition      dd ?   ; 02Ch
  150.     GetCurrentPosition   dd ?   ; 030h
  151.     ConvertTimeFormat    dd ?   ; 034h
  152.     SetPositions         dd ?   ; 038h
  153.     GetPositions         dd ?   ; 03Ch
  154.     GetAvailable         dd ?   ; 040h
  155.     SetRate              dd ?   ; 044h
  156.     GetRate              dd ?   ; 048h
  157.     GetPreroll           dd ?   ; 04Ch
  158. ends
  159.  
  160. ; GUID {56A868C0-0AD4-11CE-B03A-0020AF0BA770}
  161. IID_IMediaEventEx \
  162.     dd 056A868C0h
  163.     dw 00AD4h
  164.     dw 011CEh
  165.     db 0B0h, 03Ah, 000h, 020h, 0AFh, 00Bh, 0A7h, 070h
  166.  
  167. ; IID_IMediaEventEx Interface
  168. struct IMediaEventEx
  169.     ; IUnknown
  170.     QueryInterface         dd ?   ; 000h
  171.     AddRef                 dd ?   ; 004h
  172.     Release                dd ?   ; 008h
  173.     ; IMediaEventEx
  174.     GetTypeInfoCount       dd ?   ; 00Ch
  175.     GetTypeInfo            dd ?   ; 010h
  176.     GetIDsOfNames          dd ?   ; 014h
  177.     _Invoke                dd ?   ; 018h
  178.     GetEventHandle         dd ?   ; 01Ch
  179.     GetEvent               dd ?   ; 020h
  180.     WaitForCompletion      dd ?   ; 024h
  181.     CancelDefaultHandling  dd ?   ; 028h
  182.     RestoreDefaultHandling dd ?   ; 02Ch
  183.     FreeEventParams        dd ?   ; 030h
  184.     SetNotifyWindow        dd ?   ; 034h
  185.     SetNotifyFlags         dd ?   ; 038h
  186.     GetNotifyFlags         dd ?   ; 03Ch
  187. ends
  188.  
  189. ; GUID {56A868B5-0AD4-11CE-B03A-0020AF0BA770}
  190. IID_IBasicVideo \
  191.     dd 056A868B5h
  192.     dw 00AD4h
  193.     dw 011CEh
  194.     db 0B0h, 03Ah, 000h, 020h, 0AFh, 00Bh, 0A7h, 070h
  195.  
  196. ; IID_IBasicVideo Interface
  197. struct IBasicVideo
  198.     ; IUnknown
  199.     QueryInterface                dd ?   ; 000h
  200.     AddRef                        dd ?   ; 004h
  201.     Release                       dd ?   ; 008h
  202.     ; IBasicVideo
  203.     GetTypeInfoCount              dd ?   ; 00Ch
  204.     GetTypeInfo                   dd ?   ; 010h
  205.     GetIDsOfNames                 dd ?   ; 014h
  206.     _Invoke                       dd ?   ; 018h
  207.     get_AvgTimePerFrame           dd ?   ; 01Ch
  208.     get_BitRate                   dd ?   ; 020h
  209.     get_BitErrorRate              dd ?   ; 024h
  210.     get_VideoWidth                dd ?   ; 028h
  211.     get_VideoHeight               dd ?   ; 02Ch
  212.     put_SourceLeft                dd ?   ; 030h
  213.     get_SourceLeft                dd ?   ; 034h
  214.     put_SourceWidth               dd ?   ; 038h
  215.     get_SourceWidth               dd ?   ; 03Ch
  216.     put_SourceTop                 dd ?   ; 040h
  217.     get_SourceTop                 dd ?   ; 044h
  218.     put_SourceHeight              dd ?   ; 048h
  219.     get_SourceHeight              dd ?   ; 04Ch
  220.     put_DestinationLeft           dd ?   ; 050h
  221.     get_DestinationLeft           dd ?   ; 054h
  222.     put_DestinationWidth          dd ?   ; 058h
  223.     get_DestinationWidth          dd ?   ; 05Ch
  224.     put_DestinationTop            dd ?   ; 060h
  225.     get_DestinationTop            dd ?   ; 064h
  226.     put_DestinationHeight         dd ?   ; 068h
  227.     get_DestinationHeight         dd ?   ; 06Ch
  228.     SetSourcePosition             dd ?   ; 070h
  229.     GetSourcePosition             dd ?   ; 074h
  230.     SetDefaultSourcePosition      dd ?   ; 078h
  231.     SetDestinationPosition        dd ?   ; 07Ch
  232.     GetDestinationPosition        dd ?   ; 080h
  233.     SetDefaultDestinationPosition dd ?   ; 084h
  234.     GetVideoSize                  dd ?   ; 088h
  235.     GetVideoPaletteEntries        dd ?   ; 08Ch
  236.     GetCurrentImage               dd ?   ; 090h
  237.     IsUsingDefaultSource          dd ?   ; 094h
  238.     IsUsingDefaultDestination     dd ?   ; 098h
  239. ends
  240.  
  241. CLSCTX_INPROC_SERVER = 0x1
  242. WM_APP = 0x8000
  243. WM_GRAPHNOTIFY = WM_APP + 1
  244. EC_COMPLETE = 0x01
  245. AM_SEEKING_AbsolutePositioning = 0x1
  246.  
  247. State_Stopped = 0
  248. State_Paused = 1
  249. State_Running = 2
После стандартной инициализации COM, надо подключить основной мультимедийный модуль - интерфейс IGraphBuilder. На сайте MSDN указано, что это типа устаревшая технология, но зато она работает, начиная аж с Windows 2000 и по сегодняшний день. Поэтому не вижу смысла гоняться за чем-то иным только ради обслуживания новомодных говносистем. Получив интерфейс IGraphBuilder, с помощью метода QueryInterface получаем интерфейсы для управления медиапотоками, окнами для видео, перемоткой и т.п. Практически каждое действие завязано на собственный интерфейс.
  1.         ; Инициализация всех интерфейсов
  2.         invoke  CoCreateInstance,CLSID_FilterGraph,NULL,\
  3.                 CLSCTX_INPROC_SERVER,IID_IGraphBuilder,\
  4.                 pGraphBuilder
  5.  
  6.         mov     eax, [pGraphBuilder]
  7.         mov     eax, [eax]
  8.         stdcall dword [eax+IGraphBuilder.QueryInterface],[pGraphBuilder],\
  9.                 IID_IMediaControl,pMediaControl
  10.  
  11.         mov     eax, [pGraphBuilder]
  12.         mov     eax, [eax]
  13.         stdcall dword [eax+IGraphBuilder.QueryInterface],[pGraphBuilder],\
  14.                 IID_IVideoWindow,pVideoWindow
  15.  
  16.         mov     eax, [pGraphBuilder]
  17.         mov     eax, [eax]
  18.         stdcall dword [eax+IGraphBuilder.QueryInterface],[pGraphBuilder],\
  19.                 IID_IMediaSeeking,pMediaSeeking
  20.  
  21.         mov     eax, [pGraphBuilder]
  22.         mov     eax, [eax]
  23.         stdcall dword [eax+IGraphBuilder.QueryInterface],[pGraphBuilder],\
  24.                 IID_IMediaEventEx,pEvent
  25.  
  26.         mov     eax, [pGraphBuilder]
  27.         mov     eax, [eax]
  28.         stdcall dword [eax+IGraphBuilder.QueryInterface],[pGraphBuilder],\
  29.                 IID_IBasicVideo,pBasicVideo
Файл для воспроизведения загружается при помощи метода RenderFile. Путь к файлу обязательно должен быть в юникоде. На этом этапе уже можно определить, сможет ли плеер в принципе воспроизвести этот файл или нет. Как я упомянул в начале статьи, это зависит от установленных в системе кодеков. Всю грязную работу типа выделения памяти система берет на себя.
  1.         ; Загрузить файл для воспроизведения
  2.         mov     eax, [pGraphBuilder]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IGraphBuilder.RenderFile],[pGraphBuilder],\
  5.                 path,NULL
На следующем этапе надо подготовить окно для воспроизведения видео. Если этого не сделать, то будет создано отдельное окно. Нам же надо, чтобы видео воспроизводилось в интерфейсе нашего приложения. Это может быть, например, обычный STATIC или даже EDIT.
  1.         ; Назначить окно для воспроизведения видео
  2.         invoke  GetDlgItem,[hwnddlg],ID_VIDEO
  3.         mov     ebx,eax
  4.  
  5.         mov     eax, [pVideoWindow]
  6.         mov     eax, [eax]
  7.         stdcall dword [eax+IVideoWindow.put_Owner],[pVideoWindow],\
  8.                 ebx
  9.  
  10.         mov     eax, [pBasicVideo]
  11.         mov     eax, [eax]
  12.         stdcall dword [eax+IBasicVideo.get_VideoWidth],[pBasicVideo],\
  13.                 pWidth
  14.  
  15.         mov     eax, [pBasicVideo]
  16.         mov     eax, [eax]
  17.         stdcall dword [eax+IBasicVideo.get_VideoHeight],[pBasicVideo],\
  18.                 pHeight
  19.  
  20.         cmp     [pWidth],IMG_X
  21.         jae     loc_need_resize
  22.         cmp     [pHeight],IMG_Y
  23.         jbe     loc_create_video
  24. loc_need_resize:
  25.         ; Пресчет размеров по горизонтали
  26.         mov     eax,[pWidth]
  27.         cmp     eax,[pHeight]
  28.         jae     @f
  29.  
  30.         mov     eax,[pWidth]
  31.         xor     edx,edx
  32.         mov     ecx,IMG_Y
  33.         imul    ecx
  34.         xor     edx,edx
  35.         mov     ecx,[pHeight]
  36.         idiv    ecx
  37.         mov     [pWidth],eax
  38.         mov     [pHeight],IMG_Y
  39.         jmp     loc_create_video
  40. @@:
  41.         mov     eax,[pHeight]
  42.         xor     edx,edx
  43.         mov     ecx,IMG_X
  44.         imul    ecx
  45.         xor     edx,edx
  46.         mov     ecx,[pWidth]
  47.         idiv    ecx
  48.         mov     [pHeight],eax
  49.         mov     [pWidth],IMG_X
  50. loc_create_video:
  51.         mov     [deltaX],0
  52.         mov     [deltaY],0
  53.  
  54.         ; Смещение по X
  55.         cmp     [pWidth],IMG_X
  56.         jae     @f
  57.         mov     eax,IMG_X
  58.         sub     eax,[pWidth]
  59.         shr     eax,1
  60.         mov     [deltaX],eax
  61. @@:
  62.         ; Смещение по Y
  63.         cmp     [pHeight],IMG_Y
  64.         jae     @f
  65.         mov     eax,IMG_Y
  66.         sub     eax,[pHeight]
  67.         shr     eax,1
  68.         mov     [deltaY],eax
  69. @@:
  70.         ; Установить стиль окна
  71.         mov     eax, [pVideoWindow]
  72.         mov     eax, [eax]
  73.         stdcall dword [eax+IVideoWindow.put_WindowStyle],[pVideoWindow],\
  74.                 WS_CHILD+WS_CLIPSIBLINGS
  75.  
  76.         ; Установить размер области воспроизведения
  77.         mov     eax, [pVideoWindow]
  78.         mov     eax, [eax]
  79.         stdcall dword [eax+IVideoWindow.SetWindowPosition],[pVideoWindow],\
  80.                 [deltaX],[deltaY],[pWidth],[pHeight]
  81.  
  82.         ; Назначить окно для событий плеера
  83.         mov     eax, [pEvent]
  84.         mov     eax, [eax]
  85.         stdcall dword [eax+IMediaEventEx.SetNotifyWindow],[pEvent],\
  86.                 [hwnddlg],WM_GRAPHNOTIFY,NULL ; [hwnddlg]
  87.  
  88.         ; Заблокировать окно воспроизведения
  89.         invoke  EnableWindow,ebx,FALSE
Несколько моментов. Константы IMG_X и IMG_Y - это размеры области, в которой будет воспроизводиться видео. При помощи методов get_VideoWidth и get_VideoHeight получаем размеры видеокадра и масштабируем их в границах области воспроизведения. Дальше надо назначить окно, которое будет получать уведомление WM_GRAPHNOTIFY от графического фильтра. Еще один интересный момент, что приходится обязательно дизаблить область воспроизведения, иначе при клике на видео все приложение наглухо замирает. Объяснения этому я не нашел, может быть кто-нибудь из более опытных коллег прояснит подобное странное поведение.

Осталось только запустить файл на воспроизведение. Делается это при помощи метода Run управляющего интерфейса IMediaControl.
  1.         ; Запустить видео
  2.         mov     eax, [pMediaControl]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IMediaControl.Run],[pMediaControl]
Управлять воспроизведением можно при помощи еще двух методов, это Pause и Stop.
  1.         ; Поставить видео на паузу
  2.         mov     eax, [pMediaControl]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IMediaControl.Pause],[pMediaControl]
  1.         ; Остановить видео
  2.         mov     eax, [pMediaControl]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IMediaControl.Stop],[pMediaControl]
Получить текущее состояние воспроизведения можно при помощи метода GetState. Возможные значения состояния это "пауза", "стоп" и "воспроизведение".
  1.         ; Получить состояние воспроизведения
  2.         mov     eax, [pMediaControl]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IMediaControl.GetState],[pMediaControl],\
  5.                 0,pState
Интерфейс IMediaSeeking позволяет получить информацию о длительности медиафайла, о текущей позиции воспроизведения, а также с его помощью можно эту самую позицию передвинуть.
  1.         ; Получить длительность медиафайла
  2.         mov     eax, [pMediaSeeking]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IMediaSeeking.GetDuration],[pMediaSeeking],\
  5.                 lDuration
  1.         ; Получить текущую позицию воспроизведения
  2.         mov     eax, [pMediaSeeking]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IMediaSeeking.GetPositions],[pMediaSeeking],\
  5.                 lDuration,pStop
  1.         ; Перемотать поток на начало
  2.         mov     dword[lDuration],0
  3.         mov     dword[lDuration+4],0
  4.  
  5.         mov     eax, [pMediaSeeking]
  6.         mov     eax, [eax]
  7.         stdcall dword [eax+IMediaSeeking.SetPositions],[pMediaSeeking],\
  8.                 lDuration,AM_SEEKING_AbsolutePositioning,\
  9.                 lDuration,0
Длительность хранится в QWORD выражается в сотнях наносекунд, поэтому для перевода значения в более привычные секунды это значение надо поделить на 10000000. При установке позиции воспроизведения, соответственно, надо привести человекопонятное значение в эти же сотни наносекунд с помощью умножения.

В зависимости от тех или иных условий, графический фильтр может посылать сообщение WM_GRAPHNOTIFY назначенному ранее окну. Обработчик этого сообщения выглядит примерно следующим образом:
  1.         cmp     [msg],WM_GRAPHNOTIFY
  2.         je      wmgraph
  3.         ...
  4.         ...
  5. wmgraph:
  6.         ; Получить событие из очереди
  7.         mov     eax, [pEvent]
  8.         mov     eax, [eax]
  9.         stdcall dword [eax+IMediaEventEx.GetEvent],[pEvent],\
  10.                 evCode, param1, param2, NULL
  11.         or      eax,eax
  12.         ; Событий в очереди больше нет
  13.         jnz     processed
  14.  
  15.         ; Освободить событие
  16.         mov     eax, [pEvent]
  17.         mov     eax, [eax]
  18.         stdcall dword [eax+IMediaEventEx.FreeEventParams],[pEvent],\
  19.                 [evCode],[param1],[param2]
  20.  
  21.         ; Воспроизведение завершено?
  22.         cmp     [evCode],EC_COMPLETE
  23.         jne     @f
  24.         ...
  25.         ; Действия по завершению воспроизведения
  26.         ...
  27. @@:
  28.         ; Обработать следующее сообщение
  29.         jmp     wmgraph
При завершении работы надо освободить выделенные ресурсы. Здесь единственный момент, на который стоит обратить внимание, заключается в том, что перед релизом интерфейса событий надо отвязать окно, получающее уведомления графического фильтра.
  1.         ; Прибраться за собой
  2.         mov     eax, [pEvent]
  3.         mov     eax, [eax]
  4.         stdcall dword [eax+IMediaEventEx.SetNotifyWindow],[pEvent],\
  5.                 NULL,NULL,NULL
  6.  
  7.         mov     eax, [pEvent]
  8.         mov     eax, [eax]
  9.         stdcall dword [eax+IMediaEventEx.Release],[pEvent]
  10.  
  11.         mov     eax, [pBasicVideo]
  12.         mov     eax, [eax]
  13.         stdcall dword [eax+IBasicVideo.Release],[pBasicVideo]
  14.  
  15.         mov     eax, [pVideoWindow]
  16.         mov     eax, [eax]
  17.         stdcall dword [eax+IVideoWindow.Release],[pVideoWindow]
  18.  
  19.         mov     eax, [pMediaControl]
  20.         mov     eax, [eax]
  21.         stdcall dword [eax+IMediaControl.Release],[pMediaControl]
  22.  
  23.         mov     eax, [pMediaSeeking]
  24.         mov     eax, [eax]
  25.         stdcall dword [eax+IMediaSeeking.Release],[pMediaSeeking]
  26.  
  27.         mov     eax, [pGraphBuilder]
  28.         mov     eax, [eax]
  29.         stdcall dword [eax+IGraphBuilder.Release],[pGraphBuilder]
Всего вышеперечисленного уже должно хватить для реализации мультимедийного плеера. Получаем файл, проверяем его на поддерживаемый формат, готовим область воспроизведения, запускаем. По каким-нибудь кнопочкам выполняем паузу и воспроизведение, по таймеру отслеживаем позицию воспроизведения и каким-либо образом отображаем это в интерфейсе приложения. Что классно, воспроизведение видео и аудио производится вообще без изменения кода.

В приложении пример программы с исходным текстом, которая воспроизводит видеофайл из архива.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Multimedia.Player.Demo.zip (1,134,866 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 623 | Комментариев: 8

Комментарии

Отзывы посетителей сайта о статье
ManHunter (04.06.2024 в 11:07):
Mikl___, а чем принципиально диалог отличается от окна?
После загрузки файла методами get_VideoWidth и get_VideoHeight получаем размер видео. При этом мы знаем размер своего окна, или хотя бы панели управления плеером, и размер экрана, где располагается окно плеера. Меняем размеры диалога и EDIT'а в нем таким образом, чтобы по ширине получился размер видео, а по высоте размер видео плюс высота панели управления. Но при этом диалог делается не менее ширины панели управления и не более ширины монитора, по высоте не более высоты монитора. Кнопочки перемещаются в соответствии с шириной диалога. Для работы потребуется SetWindowPos.

В обработчике окна отслеживается несколько событий. WM_GETMINMAXINFO - для ограничения изменения размеров диалога в разрешенных пределах. WM_SIZE - для пересчета размеров элементов и перемещения кнопочек.

Ссылки в помощь:
https://www.manhunter.ru/assem...ov_okna.html
https://www.manhunter.ru/assem...ti_okna.html
https://www.manhunter.ru/assem...ckbar32.html
https://www.manhunter.ru/assem...emblere.html
Mikl___ (04.06.2024 в 02:49):
Здравствуйте ManHunter!
В случае если размер видео фрагмента оказывается больше чем поле Edit Вы подгоняете размер видео фрагмента под размер Edit'a. Как бы Вы поступили, если бы пришлось динамически изменять размер диалога под размер видео? Если бы плеер строился на базе окна -- тогда понятно, нужно использовать MoveWindow(). А что делать если плеер построен на базе диалога?
ManHunter (23.05.2024 в 08:02):
Конечно. Я именно так и сделал, только с аудиоплеером.
Mikl___ (23.05.2024 в 03:57):
Здравствуйте ManHunter!
Можно ли использовать код из Вашей статьи "Управление громкостью звука в системе" для управления громкостью звука в "Мультимедийном плеере на Ассемблере" или потребуется полная переделка управлением громкостью?
ManHunter (02.05.2024 в 13:57):
Mikl___, поддерживает не плеер, а система. Нет кодеков - нет поддержки, есть кодеки - поддерживает. У меня с установленным k-lite megapack крутит даже flv.

Тем более, что это ни в коем случае не полноценное приложение, а только каркас. Никаких проверок не делается, никакой диагностики не выводится.
Mikl___ (02.05.2024 в 13:52):
ManHunter, а mp4 ваш плейер поддерживает? Вклад в общую копилку -- посмотрите у меня в "Сказках дядюшки Римуса о x64" 52-ую главу "Братец Кролик и просмотр видео-файлов". Там россыпь разных видео-плейеров с исходным текстом и экзе
ManHunter (26.04.2024 в 11:51):
Проверено на Win7x86, Win7x64, Win10x86, Win10x64, все прекрасно работает.
User (26.04.2024 в 10:14):
как заставить воспроизводить файл из архива, или любой другой? При запуске рядом с файлом не воспроизводит. drug-n-drop не поддерживается. Через открыть как тоже

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.11 сек. / MySQL: 2 (0.0055 сек.) / Память: 4.5 Mb
Наверх