Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * DirectShow capture interface
  3.  * Copyright (c) 2010 Ramiro Polla
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "dshow_capture.h"
  23.  
  24. #include <stddef.h>
  25. #define imemoffset offsetof(libAVPin, imemvtbl)
  26.  
  27. DECLARE_QUERYINTERFACE(libAVPin,
  28.     { {&IID_IUnknown,0}, {&IID_IPin,0}, {&IID_IMemInputPin,imemoffset} })
  29. DECLARE_ADDREF(libAVPin)
  30. DECLARE_RELEASE(libAVPin)
  31.  
  32. long WINAPI
  33. libAVPin_Connect(libAVPin *this, IPin *pin, const AM_MEDIA_TYPE *type)
  34. {
  35.     dshowdebug("libAVPin_Connect(%p, %p, %p)\n", this, pin, type);
  36.     /* Input pins receive connections. */
  37.     return S_FALSE;
  38. }
  39. long WINAPI
  40. libAVPin_ReceiveConnection(libAVPin *this, IPin *pin,
  41.                            const AM_MEDIA_TYPE *type)
  42. {
  43.     enum dshowDeviceType devtype = this->filter->type;
  44.     dshowdebug("libAVPin_ReceiveConnection(%p)\n", this);
  45.  
  46.     if (!pin)
  47.         return E_POINTER;
  48.     if (this->connectedto)
  49.         return VFW_E_ALREADY_CONNECTED;
  50.  
  51.     ff_print_AM_MEDIA_TYPE(type);
  52.     if (devtype == VideoDevice) {
  53.         if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video))
  54.             return VFW_E_TYPE_NOT_ACCEPTED;
  55.     } else {
  56.         if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio))
  57.             return VFW_E_TYPE_NOT_ACCEPTED;
  58.     }
  59.  
  60.     IPin_AddRef(pin);
  61.     this->connectedto = pin;
  62.  
  63.     ff_copy_dshow_media_type(&this->type, type);
  64.  
  65.     return S_OK;
  66. }
  67. long WINAPI
  68. libAVPin_Disconnect(libAVPin *this)
  69. {
  70.     dshowdebug("libAVPin_Disconnect(%p)\n", this);
  71.  
  72.     if (this->filter->state != State_Stopped)
  73.         return VFW_E_NOT_STOPPED;
  74.     if (!this->connectedto)
  75.         return S_FALSE;
  76.     IPin_Release(this->connectedto);
  77.     this->connectedto = NULL;
  78.  
  79.     return S_OK;
  80. }
  81. long WINAPI
  82. libAVPin_ConnectedTo(libAVPin *this, IPin **pin)
  83. {
  84.     dshowdebug("libAVPin_ConnectedTo(%p)\n", this);
  85.  
  86.     if (!pin)
  87.         return E_POINTER;
  88.     if (!this->connectedto)
  89.         return VFW_E_NOT_CONNECTED;
  90.     IPin_AddRef(this->connectedto);
  91.     *pin = this->connectedto;
  92.  
  93.     return S_OK;
  94. }
  95. long WINAPI
  96. libAVPin_ConnectionMediaType(libAVPin *this, AM_MEDIA_TYPE *type)
  97. {
  98.     dshowdebug("libAVPin_ConnectionMediaType(%p)\n", this);
  99.  
  100.     if (!type)
  101.         return E_POINTER;
  102.     if (!this->connectedto)
  103.         return VFW_E_NOT_CONNECTED;
  104.  
  105.     return ff_copy_dshow_media_type(type, &this->type);
  106. }
  107. long WINAPI
  108. libAVPin_QueryPinInfo(libAVPin *this, PIN_INFO *info)
  109. {
  110.     dshowdebug("libAVPin_QueryPinInfo(%p)\n", this);
  111.  
  112.     if (!info)
  113.         return E_POINTER;
  114.  
  115.     if (this->filter)
  116.         libAVFilter_AddRef(this->filter);
  117.  
  118.     info->pFilter = (IBaseFilter *) this->filter;
  119.     info->dir     = PINDIR_INPUT;
  120.     wcscpy(info->achName, L"Capture");
  121.  
  122.     return S_OK;
  123. }
  124. long WINAPI
  125. libAVPin_QueryDirection(libAVPin *this, PIN_DIRECTION *dir)
  126. {
  127.     dshowdebug("libAVPin_QueryDirection(%p)\n", this);
  128.     if (!dir)
  129.         return E_POINTER;
  130.     *dir = PINDIR_INPUT;
  131.     return S_OK;
  132. }
  133. long WINAPI
  134. libAVPin_QueryId(libAVPin *this, wchar_t **id)
  135. {
  136.     dshowdebug("libAVPin_QueryId(%p)\n", this);
  137.  
  138.     if (!id)
  139.         return E_POINTER;
  140.  
  141.     *id = wcsdup(L"libAV Pin");
  142.  
  143.     return S_OK;
  144. }
  145. long WINAPI
  146. libAVPin_QueryAccept(libAVPin *this, const AM_MEDIA_TYPE *type)
  147. {
  148.     dshowdebug("libAVPin_QueryAccept(%p)\n", this);
  149.     return S_FALSE;
  150. }
  151. long WINAPI
  152. libAVPin_EnumMediaTypes(libAVPin *this, IEnumMediaTypes **enumtypes)
  153. {
  154.     const AM_MEDIA_TYPE *type = NULL;
  155.     libAVEnumMediaTypes *new;
  156.     dshowdebug("libAVPin_EnumMediaTypes(%p)\n", this);
  157.  
  158.     if (!enumtypes)
  159.         return E_POINTER;
  160.     new = libAVEnumMediaTypes_Create(type);
  161.     if (!new)
  162.         return E_OUTOFMEMORY;
  163.  
  164.     *enumtypes = (IEnumMediaTypes *) new;
  165.     return S_OK;
  166. }
  167. long WINAPI
  168. libAVPin_QueryInternalConnections(libAVPin *this, IPin **pin,
  169.                                   unsigned long *npin)
  170. {
  171.     dshowdebug("libAVPin_QueryInternalConnections(%p)\n", this);
  172.     return E_NOTIMPL;
  173. }
  174. long WINAPI
  175. libAVPin_EndOfStream(libAVPin *this)
  176. {
  177.     dshowdebug("libAVPin_EndOfStream(%p)\n", this);
  178.     /* I don't care. */
  179.     return S_OK;
  180. }
  181. long WINAPI
  182. libAVPin_BeginFlush(libAVPin *this)
  183. {
  184.     dshowdebug("libAVPin_BeginFlush(%p)\n", this);
  185.     /* I don't care. */
  186.     return S_OK;
  187. }
  188. long WINAPI
  189. libAVPin_EndFlush(libAVPin *this)
  190. {
  191.     dshowdebug("libAVPin_EndFlush(%p)\n", this);
  192.     /* I don't care. */
  193.     return S_OK;
  194. }
  195. long WINAPI
  196. libAVPin_NewSegment(libAVPin *this, REFERENCE_TIME start, REFERENCE_TIME stop,
  197.                     double rate)
  198. {
  199.     dshowdebug("libAVPin_NewSegment(%p)\n", this);
  200.     /* I don't care. */
  201.     return S_OK;
  202. }
  203.  
  204. static int
  205. libAVPin_Setup(libAVPin *this, libAVFilter *filter)
  206. {
  207.     IPinVtbl *vtbl = this->vtbl;
  208.     IMemInputPinVtbl *imemvtbl;
  209.  
  210.     if (!filter)
  211.         return 0;
  212.  
  213.     imemvtbl = av_malloc(sizeof(IMemInputPinVtbl));
  214.     if (!imemvtbl)
  215.         return 0;
  216.  
  217.     SETVTBL(imemvtbl, libAVMemInputPin, QueryInterface);
  218.     SETVTBL(imemvtbl, libAVMemInputPin, AddRef);
  219.     SETVTBL(imemvtbl, libAVMemInputPin, Release);
  220.     SETVTBL(imemvtbl, libAVMemInputPin, GetAllocator);
  221.     SETVTBL(imemvtbl, libAVMemInputPin, NotifyAllocator);
  222.     SETVTBL(imemvtbl, libAVMemInputPin, GetAllocatorRequirements);
  223.     SETVTBL(imemvtbl, libAVMemInputPin, Receive);
  224.     SETVTBL(imemvtbl, libAVMemInputPin, ReceiveMultiple);
  225.     SETVTBL(imemvtbl, libAVMemInputPin, ReceiveCanBlock);
  226.  
  227.     this->imemvtbl = imemvtbl;
  228.  
  229.     SETVTBL(vtbl, libAVPin, QueryInterface);
  230.     SETVTBL(vtbl, libAVPin, AddRef);
  231.     SETVTBL(vtbl, libAVPin, Release);
  232.     SETVTBL(vtbl, libAVPin, Connect);
  233.     SETVTBL(vtbl, libAVPin, ReceiveConnection);
  234.     SETVTBL(vtbl, libAVPin, Disconnect);
  235.     SETVTBL(vtbl, libAVPin, ConnectedTo);
  236.     SETVTBL(vtbl, libAVPin, ConnectionMediaType);
  237.     SETVTBL(vtbl, libAVPin, QueryPinInfo);
  238.     SETVTBL(vtbl, libAVPin, QueryDirection);
  239.     SETVTBL(vtbl, libAVPin, QueryId);
  240.     SETVTBL(vtbl, libAVPin, QueryAccept);
  241.     SETVTBL(vtbl, libAVPin, EnumMediaTypes);
  242.     SETVTBL(vtbl, libAVPin, QueryInternalConnections);
  243.     SETVTBL(vtbl, libAVPin, EndOfStream);
  244.     SETVTBL(vtbl, libAVPin, BeginFlush);
  245.     SETVTBL(vtbl, libAVPin, EndFlush);
  246.     SETVTBL(vtbl, libAVPin, NewSegment);
  247.  
  248.     this->filter = filter;
  249.  
  250.     return 1;
  251. }
  252. DECLARE_CREATE(libAVPin, libAVPin_Setup(this, filter), libAVFilter *filter)
  253. DECLARE_DESTROY(libAVPin, nothing)
  254.  
  255. /*****************************************************************************
  256.  * libAVMemInputPin
  257.  ****************************************************************************/
  258. long WINAPI
  259. libAVMemInputPin_QueryInterface(libAVMemInputPin *this, const GUID *riid,
  260.                                 void **ppvObject)
  261. {
  262.     libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
  263.     dshowdebug("libAVMemInputPin_QueryInterface(%p)\n", this);
  264.     return libAVPin_QueryInterface(pin, riid, ppvObject);
  265. }
  266. unsigned long WINAPI
  267. libAVMemInputPin_AddRef(libAVMemInputPin *this)
  268. {
  269.     libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
  270.     dshowdebug("libAVMemInputPin_AddRef(%p)\n", this);
  271.     return libAVPin_AddRef(pin);
  272. }
  273. unsigned long WINAPI
  274. libAVMemInputPin_Release(libAVMemInputPin *this)
  275. {
  276.     libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
  277.     dshowdebug("libAVMemInputPin_Release(%p)\n", this);
  278.     return libAVPin_Release(pin);
  279. }
  280. long WINAPI
  281. libAVMemInputPin_GetAllocator(libAVMemInputPin *this, IMemAllocator **alloc)
  282. {
  283.     dshowdebug("libAVMemInputPin_GetAllocator(%p)\n", this);
  284.     return VFW_E_NO_ALLOCATOR;
  285. }
  286. long WINAPI
  287. libAVMemInputPin_NotifyAllocator(libAVMemInputPin *this, IMemAllocator *alloc,
  288.                                  BOOL rdwr)
  289. {
  290.     dshowdebug("libAVMemInputPin_NotifyAllocator(%p)\n", this);
  291.     return S_OK;
  292. }
  293. long WINAPI
  294. libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin *this,
  295.                                           ALLOCATOR_PROPERTIES *props)
  296. {
  297.     dshowdebug("libAVMemInputPin_GetAllocatorRequirements(%p)\n", this);
  298.     return E_NOTIMPL;
  299. }
  300. long WINAPI
  301. libAVMemInputPin_Receive(libAVMemInputPin *this, IMediaSample *sample)
  302. {
  303.     libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
  304.     enum dshowDeviceType devtype = pin->filter->type;
  305.     void *priv_data;
  306.     uint8_t *buf;
  307.     int buf_size;
  308.     int index;
  309.     int64_t curtime;
  310.  
  311.     dshowdebug("libAVMemInputPin_Receive(%p)\n", this);
  312.  
  313.     if (!sample)
  314.         return E_POINTER;
  315.  
  316.     if (devtype == VideoDevice) {
  317.         /* PTS from video devices is unreliable. */
  318.         IReferenceClock *clock = pin->filter->clock;
  319.         IReferenceClock_GetTime(clock, &curtime);
  320.     } else {
  321.         int64_t dummy;
  322.         IMediaSample_GetTime(sample, &curtime, &dummy);
  323.         curtime += pin->filter->start_time;
  324.     }
  325.  
  326.     buf_size = IMediaSample_GetActualDataLength(sample);
  327.     IMediaSample_GetPointer(sample, &buf);
  328.     priv_data = pin->filter->priv_data;
  329.     index = pin->filter->stream_index;
  330.  
  331.     pin->filter->callback(priv_data, index, buf, buf_size, curtime);
  332.  
  333.     return S_OK;
  334. }
  335. long WINAPI
  336. libAVMemInputPin_ReceiveMultiple(libAVMemInputPin *this,
  337.                                  IMediaSample **samples, long n, long *nproc)
  338. {
  339.     int i;
  340.     dshowdebug("libAVMemInputPin_ReceiveMultiple(%p)\n", this);
  341.  
  342.     for (i = 0; i < n; i++)
  343.         libAVMemInputPin_Receive(this, samples[i]);
  344.  
  345.     *nproc = n;
  346.     return S_OK;
  347. }
  348. long WINAPI
  349. libAVMemInputPin_ReceiveCanBlock(libAVMemInputPin *this)
  350. {
  351.     dshowdebug("libAVMemInputPin_ReceiveCanBlock(%p)\n", this);
  352.     /* I swear I will not block. */
  353.     return S_FALSE;
  354. }
  355.  
  356. void
  357. libAVMemInputPin_Destroy(libAVMemInputPin *this)
  358. {
  359.     libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
  360.     dshowdebug("libAVMemInputPin_Destroy(%p)\n", this);
  361.     libAVPin_Destroy(pin);
  362. }
  363.