videohorflip.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include "stdafx.h"
  2. #include <InitGuid.h>
  3. #include "filter.h"
  4. #include "videohorflip.h"
  5. #include <algorithm>
  6. #include <immintrin.h>
  7. using namespace std;
  8. //
  9. // VideoHozFlipFilter
  10. //
  11. VideoHozFlipFilter::VideoHozFlipFilter( LPUNKNOWN punk, HRESULT *phr ) : CTransInPlaceFilter(NAME("VideoHozFlip"), punk, CLSID_VideoHozFlip, phr)
  12. {
  13. //_mm_shuffle_epi8()
  14. }
  15. HRESULT VideoHozFlipFilter::Transform( IMediaSample *pSample )
  16. {
  17. LPBYTE lpData;
  18. pSample->GetPointer(&lpData);
  19. AM_MEDIA_TYPE *pType = &InputPin()->CurrentMediaType();
  20. VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
  21. int cxImage = pvi->bmiHeader.biWidth;
  22. int cyImage = pvi->bmiHeader.biHeight;
  23. unsigned char *data[4] = {lpData, 0, 0, 0};
  24. int linesize[4] = {cxImage*3, 0, 0, 0};
  25. videohorflip_transform(data, linesize, cxImage, cyImage, 2);
  26. return S_OK;
  27. }
  28. HRESULT VideoHozFlipFilter::CheckInputType( const CMediaType *mtIn )
  29. {
  30. VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*)mtIn->pbFormat;
  31. if (mtIn->majortype != MEDIATYPE_Video) // check media type
  32. {
  33. return VFW_E_TYPE_NOT_ACCEPTED;
  34. }
  35. // check subtype and formattype
  36. if (mtIn->subtype != MEDIASUBTYPE_RGB24 ||
  37. mtIn->formattype != FORMAT_VideoInfo ||
  38. mtIn->cbFormat < sizeof(VIDEOINFOHEADER))
  39. {
  40. return VFW_E_TYPE_NOT_ACCEPTED;
  41. }
  42. return S_OK;
  43. }
  44. CUnknown * WINAPI VideoHozFlipFilter::CreateInstance( LPUNKNOWN punk, HRESULT *phr )
  45. {
  46. ASSERT(phr);
  47. VideoHozFlipFilter *pFilter = new VideoHozFlipFilter(punk, phr);
  48. if (pFilter == NULL) {
  49. if (phr)
  50. *phr = E_OUTOFMEMORY;
  51. }
  52. return pFilter;
  53. }
  54. //
  55. // VideoGrabberRenderFilter
  56. //
  57. VideoGrabberRenderFilter::VideoGrabberRenderFilter( LPUNKNOWN punk, HRESULT *phr ) : CBaseRenderer(CLSID_VideoGrabberRender, NAME("VideoGrabberRender"), punk, phr),
  58. m_user_data(NULL), m_on_sample(NULL)
  59. {
  60. }
  61. CUnknown * WINAPI VideoGrabberRenderFilter::CreateInstance( LPUNKNOWN punk, HRESULT *phr )
  62. {
  63. ASSERT(phr);
  64. VideoGrabberRenderFilter *pFilter = new VideoGrabberRenderFilter(punk, phr);
  65. if (pFilter == NULL) {
  66. if (phr)
  67. *phr = E_OUTOFMEMORY;
  68. }
  69. return pFilter;
  70. }
  71. HRESULT VideoGrabberRenderFilter::DoRenderSample( IMediaSample *pMediaSample )
  72. {
  73. if (m_on_sample) {
  74. LPBYTE lpData;
  75. if (SUCCEEDED(pMediaSample->GetPointer(&lpData))) {
  76. (*m_on_sample)(m_user_data, lpData);
  77. }
  78. }
  79. return S_OK;
  80. }
  81. HRESULT VideoGrabberRenderFilter::CheckMediaType( const CMediaType * mtIn)
  82. {
  83. VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*)mtIn->pbFormat;
  84. if (mtIn->majortype != MEDIATYPE_Video) // check media type
  85. {
  86. return VFW_E_TYPE_NOT_ACCEPTED;
  87. }
  88. // check subtype and formattype
  89. if (mtIn->subtype != MEDIASUBTYPE_RGB24 ||
  90. mtIn->formattype != FORMAT_VideoInfo ||
  91. mtIn->cbFormat < sizeof(VIDEOINFOHEADER))
  92. {
  93. return VFW_E_TYPE_NOT_ACCEPTED;
  94. }
  95. return S_OK;
  96. }
  97. VIDEOHORFLIP_API(void*) videohorflip_create_filter()
  98. {
  99. HRESULT hr = S_OK;
  100. CUnknown *pUnknown = VideoHozFlipFilter::CreateInstance(NULL, &hr);
  101. IBaseFilter *pBaseFilter = NULL;
  102. if (SUCCEEDED(hr)) {
  103. pUnknown->NonDelegatingAddRef();
  104. hr = pUnknown->NonDelegatingQueryInterface(IID_IBaseFilter, (void**)&pBaseFilter);
  105. pUnknown->NonDelegatingRelease();
  106. }
  107. return pBaseFilter;
  108. }
  109. VIDEOHORFLIP_API(void*) videohorflip_create_grabber_render(void (*on_sample)(void *user_data, void *data), void *user_data)
  110. {
  111. HRESULT hr = S_OK;
  112. CUnknown *pUnknown = VideoGrabberRenderFilter::CreateInstance(NULL, &hr);
  113. IBaseFilter *pBaseFilter = NULL;
  114. if (SUCCEEDED(hr)) {
  115. pUnknown->NonDelegatingAddRef();
  116. hr = pUnknown->NonDelegatingQueryInterface(IID_IBaseFilter, (void**)&pBaseFilter);
  117. pUnknown->NonDelegatingRelease();
  118. if (SUCCEEDED(hr)) {
  119. VideoGrabberRenderFilter *pGrabberRender = dynamic_cast<VideoGrabberRenderFilter *>(pUnknown);
  120. pGrabberRender->SetCallback(on_sample, user_data);
  121. }
  122. }
  123. return pBaseFilter;
  124. }
  125. VIDEOHORFLIP_API(int) videohorflip_transform(unsigned char *data[], int linesize[], int cxImage, int cyImage, int format)
  126. {
  127. if (format == 2) { // rgb24
  128. int i, j;
  129. LPBYTE lpData = data[0];
  130. for (i = 0; i < cyImage; ++i) {
  131. LPBYTE x = lpData;
  132. LPBYTE y = x + (cxImage-1) * 3;
  133. for (j = 0; j < cxImage >> 1; ++j) {
  134. swap(*x, *y);
  135. x++;
  136. y++;
  137. swap(*x, *y);
  138. x++;
  139. y++;
  140. swap(*x, *y);
  141. x++;
  142. y-=5;
  143. }
  144. lpData += linesize[0];
  145. }
  146. return 0;
  147. } else {
  148. return -1; // not support other types currently
  149. }
  150. }
  151. VIDEOHORFLIP_API(void) videohorflip_fast_copy(void *dst, const void *src, int size)
  152. {
  153. #if 1
  154. if (((int)dst&0xf) == 0 && ((int)src&0xf)==0) { // 16 byte alignment
  155. int i;
  156. int n = size / 128;
  157. __m128i xmm0;
  158. __m128i xmm1;
  159. __m128i xmm2;
  160. __m128i xmm3;
  161. __m128i xmm4;
  162. __m128i xmm5;
  163. __m128i xmm6;
  164. __m128i xmm7;
  165. const __m128i *source = reinterpret_cast<const __m128i *>(src);
  166. __m128i *destination = reinterpret_cast<__m128i*>(dst);
  167. for (i = 0; i < n; ++i) {
  168. _mm_prefetch((const char*)source, _MM_HINT_NTA);
  169. _mm_prefetch((const char*)source+64, _MM_HINT_NTA);
  170. _mm_prefetch((const char*)source+128, _MM_HINT_NTA);
  171. xmm0 = _mm_load_si128(source++);
  172. xmm1 = _mm_load_si128(source++);
  173. xmm2 = _mm_load_si128(source++);
  174. xmm3 = _mm_load_si128(source++);
  175. xmm4 = _mm_load_si128(source++);
  176. xmm5 = _mm_load_si128(source++);
  177. xmm6 = _mm_load_si128(source++);
  178. xmm7 = _mm_load_si128(source++);
  179. _mm_stream_si128(destination++, xmm0);
  180. _mm_stream_si128(destination++, xmm1);
  181. _mm_stream_si128(destination++, xmm2);
  182. _mm_stream_si128(destination++, xmm3);
  183. _mm_stream_si128(destination++, xmm4);
  184. _mm_stream_si128(destination++, xmm5);
  185. _mm_stream_si128(destination++, xmm6);
  186. _mm_stream_si128(destination++, xmm7);
  187. }
  188. n = (size % 128) / 16;
  189. for (i = 0; i < n; ++i) {
  190. _mm_prefetch((const char*)source, _MM_HINT_NTA);
  191. xmm0 = _mm_load_si128(source++);
  192. _mm_stream_si128(destination++, xmm0);
  193. }
  194. } else {
  195. memcpy(dst, src, size);
  196. }
  197. #else
  198. memcpy(dst, src, size);
  199. #endif
  200. }
  201. // counter clockwise
  202. static void rotate1(const unsigned char *src_data, int width, int height, unsigned char *dst_data)
  203. {
  204. int i, j;
  205. int src_linesize = width * 3;
  206. int dst_linesize = height * 3;
  207. const unsigned char *pp = src_data + (height-1) * src_linesize;
  208. const unsigned char *p;
  209. unsigned char *ss = dst_data;
  210. unsigned char *s;
  211. for (i = 0; i < height; ++i) {
  212. p = pp;
  213. s = ss;
  214. for (j = 0; j < width; ++j) {
  215. s[0] = p[0];
  216. s[1] = p[1];
  217. s[2] = p[2];
  218. s += dst_linesize;
  219. p += 3;
  220. }
  221. ss += 3;
  222. pp -= src_linesize;
  223. }
  224. }
  225. // clockwise
  226. static void rotate2(const unsigned char *src_data, int width, int height, unsigned char *dst_data)
  227. {
  228. int i, j;
  229. int src_linesize = width * 3;
  230. int dst_linesize = height * 3;
  231. const unsigned char *pp = src_data + (width-1)*3;
  232. const unsigned char *p;
  233. unsigned char *ss = dst_data;
  234. unsigned char *s;
  235. for (i = 0; i < height; ++i) {
  236. p = pp;
  237. s = ss;
  238. for (j = 0; j < width; ++j) {
  239. s[0] = p[0];
  240. s[1] = p[1];
  241. s[2] = p[2];
  242. s += dst_linesize;
  243. p -= 3;
  244. }
  245. pp += src_linesize;
  246. ss += 3;
  247. }
  248. }
  249. VIDEOHORFLIP_API(int) videohorflip_rotate(const unsigned char *src_data, int width, int height, unsigned char *dst_data, int rotation)
  250. {
  251. if (rotation == 1) {
  252. rotate1(src_data, width, height, dst_data);
  253. } else if (rotation == -1) {
  254. rotate2(src_data, width, height, dst_data);
  255. } else { // unknown rotation param
  256. return -1;
  257. }
  258. return 0;
  259. }