gstdspipp.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850
  1. /*
  2. * Copyright (C) 2010 Nokia Corporation
  3. *
  4. * Authors:
  5. * Elamparithi Shanmugam <parithi@ti.com>
  6. * Felipe Contreras <felipe.contreras@nokia.com>
  7. *
  8. * This file may be used under the terms of the GNU Lesser General Public
  9. * License version 2.1, a copy of which is found in LICENSE included in the
  10. * packaging of this file.
  11. */
  12. #include "gstdspipp.h"
  13. #include "util.h"
  14. static GstDspBaseClass *parent_class;
  15. #define MAX_ALGS 16
  16. #define IPP_TIMEOUT 2
  17. #define MAX_WIDTH 4096
  18. #define MAX_HEIGHT 3072
  19. #define MAX_TOTAL_PIXEL (4000 * 3008)
  20. #ifndef gst_pad_get_caps_reffed
  21. #define gst_pad_get_caps_reffed(p) gst_pad_get_caps(p)
  22. #endif
  23. #ifndef gst_pad_peer_get_caps_reffed
  24. #define gst_pad_peer_get_caps_reffed(p) gst_pad_peer_get_caps(p)
  25. #endif
  26. #if SN_API == 0
  27. #define INTERNAL_FORMAT IPP_YUV_422P
  28. #else
  29. #define INTERNAL_FORMAT IPP_YUV_420P
  30. #endif
  31. #define OVERWRITE_INPUT_BUFFER 1
  32. static bool send_stop_message(GstDspBase *base);
  33. static gboolean sink_event(GstDspBase *base, GstEvent *event);
  34. static void send_processing_info_gstmessage(GstDspIpp *self, const gchar* info);
  35. static GstCaps *getcaps(GstPad * pad);
  36. enum {
  37. PROP_0,
  38. PROP_NOISE_FILTER_STRENGTH,
  39. };
  40. enum {
  41. NOISE_FILTER_CUSTOM,
  42. NOISE_FILTER_NORMAL,
  43. NOISE_FILTER_AGGRESSIVE,
  44. };
  45. enum {
  46. IPP_YUV_420P = 1,
  47. IPP_YUV_422P,
  48. IPP_YUV_422IBE,
  49. IPP_YUV_422ILE,
  50. IPP_YUV_444P,
  51. IPP_YUV_411P,
  52. IPP_GRAY,
  53. IPP_RGB,
  54. };
  55. enum {
  56. DFGM_CREATE_XBF,
  57. DFGM_DESTROY_XBF,
  58. DFGM_SET_XBF_ALGS,
  59. DFGM_CLEAR_XBF_ALGS,
  60. DFGM_GET_MEM_REQ,
  61. DFGM_CREATE_XBF_PIPE,
  62. DFGM_DESTROY_XBF_PIPE,
  63. DFGM_START_PROCESSING,
  64. DFGM_STOP_PROCESSING,
  65. DFGM_QUEUE_BUFF,
  66. DFGM_CONTROL_PIPE,
  67. DFGM_FLUSH_PIPE,
  68. DFGM_EXIT,
  69. };
  70. enum {
  71. DFGM_CREATE_XBF_ACK = 0x1000,
  72. DFGM_DESTROY_XBF_ACK,
  73. DFGM_SET_XBF_ALGS_ACK,
  74. DFGM_CLEAR_XBF_ALGS_ACK,
  75. DFGM_GET_MEM_REQ_ACK,
  76. DFGM_CREATE_XBF_PIPE_ACK,
  77. DFGM_DESTROY_XBF_PIPE_ACK,
  78. DFGM_START_PROCESSING_ACK,
  79. DFGM_STOP_PROCESSING_ACK,
  80. DFGM_CONTROL_PIPE_ACK,
  81. DFGM_FLUSH_PIPE_ACK,
  82. DFGM_FREE_BUFF,
  83. DFGM_EVENT_ERROR,
  84. DFGM_EXIT_ACK,
  85. };
  86. enum {
  87. DFGM_ERROR_NONE = 0,
  88. DFGM_ERROR_CREATE_XBF = 0x0100,
  89. DFGM_ERROR_DESTROY_XBF = 0x0200,
  90. DFGM_ERROR_SET_ALGS = 0x0400,
  91. DFGM_ERROR_DESTROY_ALGS = 0x0800,
  92. DFGM_ERROR_CREATE_XBF_PIPE = 0x2000,
  93. DFGM_ERROR_DESTROY_XBF_PIPE = 0x4000,
  94. DFGM_ERROR_CONTROL_PIPE = 0x8000,
  95. DFGM_ERROR_QUEUE_BUFF = 0x10000,
  96. DFGM_ERROR_INVALID_STATE = 0x80000
  97. };
  98. enum {
  99. CONTENT_TYPE_BUFFER,
  100. CONTENT_TYPE_IN_ARGS,
  101. CONTENT_TYPE_OUT_ARGS,
  102. };
  103. struct ipp_name_string {
  104. int8_t str[25];
  105. uint32_t size;
  106. };
  107. #define GST_TYPE_IPP_NOISE_FILTER_STRENGTH (gst_dsp_ipp_get_noise_filter_type())
  108. static GType
  109. gst_dsp_ipp_get_noise_filter_type(void)
  110. {
  111. static GType gst_dspipp_strength_type;
  112. static GEnumValue strength[] = {
  113. {NOISE_FILTER_CUSTOM, "Custom", "custom"},
  114. {NOISE_FILTER_NORMAL, "Normal", "normal"},
  115. {NOISE_FILTER_AGGRESSIVE, "Aggressive", "aggressive"},
  116. {0, NULL, NULL},
  117. };
  118. if (G_UNLIKELY(!gst_dspipp_strength_type)) {
  119. gst_dspipp_strength_type =
  120. g_enum_register_static("GstDspIppNoiseFilterStrength", strength);
  121. }
  122. return gst_dspipp_strength_type;
  123. }
  124. #define DEFAULT_NOISE_FILTER_STRENGTH NOISE_FILTER_CUSTOM
  125. static inline dmm_buffer_t *ipp_calloc(GstDspIpp *self, size_t size, int dir)
  126. {
  127. GstDspBase *base = GST_DSP_BASE(self);
  128. return dmm_buffer_calloc(base->dsp_handle, base->proc, size, dir);
  129. }
  130. /* star algo */
  131. struct ipp_star_algo_create_params {
  132. uint32_t size;
  133. int32_t num_in_bufs;
  134. int32_t num_out_bufs;
  135. };
  136. struct ipp_star_algo_in_args {
  137. uint32_t size;
  138. };
  139. struct ipp_star_algo_out_args {
  140. uint32_t size;
  141. int32_t error;
  142. };
  143. static struct ipp_algo *
  144. get_star_params(GstDspIpp *self)
  145. {
  146. struct ipp_algo *algo;
  147. dmm_buffer_t *tmp;
  148. struct ipp_star_algo_create_params *params;
  149. struct ipp_star_algo_in_args *in_args;
  150. struct ipp_star_algo_out_args *out_args;
  151. algo = calloc(1, sizeof(*algo));
  152. if (!algo)
  153. return NULL;
  154. tmp = ipp_calloc(self, sizeof(*params), DMA_TO_DEVICE);
  155. params = tmp->data;
  156. params->size = sizeof(*params);
  157. params->num_in_bufs = 3;
  158. dmm_buffer_map(tmp);
  159. algo->create_params = tmp;
  160. algo->fxn = "STAR_ALG";
  161. tmp = ipp_calloc(self, sizeof(*in_args), DMA_TO_DEVICE);
  162. in_args = tmp->data;
  163. in_args->size = sizeof(*in_args);
  164. dmm_buffer_map(tmp);
  165. algo->in = tmp;
  166. tmp = ipp_calloc(self, sizeof(*out_args), DMA_BIDIRECTIONAL);
  167. out_args = tmp->data;
  168. out_args->size = sizeof(*out_args);
  169. dmm_buffer_map(tmp);
  170. algo->out = tmp;
  171. return algo;
  172. }
  173. /* yuv conversion */
  174. struct ipp_crcbs_yuv_algo_create_params {
  175. uint32_t size;
  176. int32_t max_width;
  177. int32_t max_height;
  178. int32_t error_code;
  179. };
  180. struct ipp_yuvc_algo_in_args {
  181. uint32_t size;
  182. int32_t input_height;
  183. int32_t input_width;
  184. int32_t output_chroma_format;
  185. int32_t input_chroma_format;
  186. };
  187. struct ipp_yuvc_algo_out_args {
  188. uint32_t size;
  189. int32_t extended_error;
  190. int32_t output_chroma_format;
  191. int32_t out_buf_size;
  192. int32_t out_width;
  193. int32_t out_height;
  194. };
  195. static struct ipp_algo *
  196. get_yuvc_params(GstDspIpp *self, int in_fmt, int out_fmt)
  197. {
  198. struct ipp_algo *algo;
  199. dmm_buffer_t *tmp;
  200. struct ipp_crcbs_yuv_algo_create_params *params;
  201. struct ipp_yuvc_algo_in_args *in_args;
  202. struct ipp_yuvc_algo_out_args *out_args;
  203. algo = calloc(1, sizeof(*algo));
  204. if (!algo)
  205. return NULL;
  206. tmp = ipp_calloc(self, sizeof(*params), DMA_TO_DEVICE);
  207. params = tmp->data;
  208. params->size = sizeof(*params);
  209. params->max_width = self->width;
  210. params->max_height = self->height;
  211. dmm_buffer_map(tmp);
  212. algo->create_params = tmp;
  213. algo->fxn = "YUVCONVERT_IYUVCONVERT";
  214. algo->dma_fxn = "YUVCONVERT_TI_IDMA3";
  215. tmp = ipp_calloc(self, sizeof(*in_args), DMA_TO_DEVICE);
  216. in_args = tmp->data;
  217. in_args->size = sizeof(*in_args);
  218. in_args->input_width = self->width;
  219. in_args->input_height = self->height;
  220. in_args->input_chroma_format = in_fmt;
  221. in_args->output_chroma_format = out_fmt;
  222. dmm_buffer_map(tmp);
  223. algo->in = tmp;
  224. tmp = ipp_calloc(self, sizeof(*out_args), DMA_BIDIRECTIONAL);
  225. out_args = tmp->data;
  226. out_args->size = sizeof(*out_args);
  227. dmm_buffer_map(tmp);
  228. algo->out = tmp;
  229. return algo;
  230. }
  231. /* chroma suppression */
  232. struct ipp_crcbs_algo_in_args {
  233. uint32_t size;
  234. int32_t input_height;
  235. int32_t input_width;
  236. int32_t input_chroma_format;
  237. };
  238. struct ipp_crcbs_algo_out_args {
  239. uint32_t size;
  240. int32_t extended_error;
  241. int32_t out_buf_size;
  242. int32_t out_width;
  243. int32_t out_height;
  244. };
  245. static struct ipp_algo *
  246. get_crcbs_params(GstDspIpp *self)
  247. {
  248. struct ipp_algo *algo;
  249. dmm_buffer_t *tmp;
  250. struct ipp_crcbs_yuv_algo_create_params *params;
  251. struct ipp_crcbs_algo_in_args *in_args;
  252. struct ipp_crcbs_algo_out_args *out_args;
  253. algo = calloc(1, sizeof(*algo));
  254. if (!algo)
  255. return NULL;
  256. tmp = ipp_calloc(self, sizeof(*params), DMA_TO_DEVICE);
  257. params = tmp->data;
  258. params->size = sizeof(*params);
  259. params->max_width = self->width;
  260. params->max_height = self->height;
  261. dmm_buffer_map(tmp);
  262. algo->create_params = tmp;
  263. algo->fxn = "CRCBS_ICRCBS";
  264. algo->dma_fxn = "CRCBS_TI_IDMA3";
  265. tmp = ipp_calloc(self, sizeof(*in_args), DMA_TO_DEVICE);
  266. in_args = tmp->data;
  267. in_args->size = sizeof(*in_args);
  268. in_args->input_width = self->width;
  269. in_args->input_height = self->height;
  270. in_args->input_chroma_format = INTERNAL_FORMAT;
  271. dmm_buffer_map(tmp);
  272. algo->in = tmp;
  273. tmp = ipp_calloc(self, sizeof(*out_args), DMA_BIDIRECTIONAL);
  274. out_args = tmp->data;
  275. out_args->size = sizeof(*out_args);
  276. dmm_buffer_map(tmp);
  277. algo->out = tmp;
  278. return algo;
  279. }
  280. /* EENF: Edge Enhancement and Noise Filter */
  281. struct ipp_eenf_algo_create_params {
  282. uint32_t size;
  283. int32_t input_buffer_size_for_in_place;
  284. int16_t in_place;
  285. int16_t error_code;
  286. int16_t max_image_size_v;
  287. int16_t max_image_size_h;
  288. };
  289. struct ipp_eenf_algo_in_args {
  290. uint32_t size;
  291. int32_t input_chroma_format;
  292. int16_t in_full_width;
  293. int16_t in_full_height;
  294. int16_t in_offset_v;
  295. int16_t in_offset_h;
  296. int16_t input_width;
  297. int16_t input_height;
  298. int16_t in_place;
  299. int16_t nf_processing;
  300. };
  301. struct ipp_eenf_algo_out_args {
  302. uint32_t size;
  303. int32_t extended_error;
  304. int16_t out_width;
  305. int16_t out_height;
  306. };
  307. static struct ipp_algo *
  308. get_eenf_params(GstDspIpp *self)
  309. {
  310. struct ipp_algo *algo;
  311. dmm_buffer_t *tmp;
  312. struct ipp_eenf_algo_create_params *params;
  313. struct ipp_eenf_algo_in_args *in_args;
  314. struct ipp_eenf_algo_out_args *out_args;
  315. algo = calloc(1, sizeof(*algo));
  316. if (!algo)
  317. return NULL;
  318. tmp = ipp_calloc(self, sizeof(*params), DMA_TO_DEVICE);
  319. params = tmp->data;
  320. params->size = sizeof(*params);
  321. params->max_image_size_v = self->height;
  322. params->max_image_size_h = self->width;
  323. dmm_buffer_map(tmp);
  324. algo->create_params = tmp;
  325. algo->fxn = "EENF_IEENF";
  326. algo->dma_fxn = "EENF_TI_IDMA3";
  327. tmp = ipp_calloc(self, sizeof(*in_args), DMA_TO_DEVICE);
  328. in_args = tmp->data;
  329. in_args->size = sizeof(*in_args);
  330. in_args->input_chroma_format = INTERNAL_FORMAT;
  331. in_args->in_full_width = self->width;
  332. in_args->in_full_height = self->height;
  333. in_args->input_width = self->width;
  334. in_args->input_height = self->height;
  335. dmm_buffer_map(tmp);
  336. algo->in = tmp;
  337. tmp = ipp_calloc(self, sizeof(*out_args), DMA_BIDIRECTIONAL);
  338. out_args = tmp->data;
  339. out_args->size = sizeof(*out_args);
  340. dmm_buffer_map(tmp);
  341. algo->out = tmp;
  342. return algo;
  343. }
  344. static bool setup_ipp_params(GstDspIpp *self)
  345. {
  346. int i = 0;
  347. self->algos[i++] = get_star_params(self);
  348. if (self->in_pix_fmt != INTERNAL_FORMAT)
  349. self->algos[i++] = get_yuvc_params(self, IPP_YUV_422ILE, INTERNAL_FORMAT);
  350. self->algos[i++] = get_crcbs_params(self);
  351. self->algos[i++] = get_eenf_params(self);
  352. self->algos[i++] = get_yuvc_params(self, INTERNAL_FORMAT, IPP_YUV_422ILE);
  353. self->nr_algos = i;
  354. return true;
  355. }
  356. static void free_message_args(GstDspIpp *self)
  357. {
  358. unsigned i;
  359. dmm_buffer_t **c;
  360. c = self->msg_ptr;
  361. for (i = 0; i < ARRAY_SIZE(self->msg_ptr); i++, c++) {
  362. dmm_buffer_free(*c);
  363. *c = NULL;
  364. }
  365. }
  366. static void ipp_buffer_begin(GstDspIpp *self)
  367. {
  368. unsigned i;
  369. dmm_buffer_t **c = self->msg_ptr;
  370. for (i = 0; i < ARRAY_SIZE(self->msg_ptr); i++, c++) {
  371. if (!*c)
  372. continue;
  373. dmm_buffer_begin(*c, (*c)->size);
  374. }
  375. }
  376. static void ipp_buffer_end(GstDspIpp *self)
  377. {
  378. unsigned i;
  379. dmm_buffer_t **c = self->msg_ptr;
  380. for (i = 0; i < ARRAY_SIZE(self->msg_ptr); i++, c++) {
  381. if (!*c)
  382. continue;
  383. dmm_buffer_end(*c, (*c)->size);
  384. }
  385. }
  386. struct xbf_msg_elem_2 {
  387. uint32_t size;
  388. uint32_t error_code;
  389. };
  390. static void got_message(GstDspBase *base, struct dsp_msg *msg)
  391. {
  392. GstDspIpp *self = GST_DSP_IPP(base);
  393. int command_id = msg->cmd;
  394. int error_code = 0;
  395. dmm_buffer_t **msg_ptr = self->msg_ptr;
  396. ipp_buffer_end(self);
  397. if (msg_ptr[1]) {
  398. struct xbf_msg_elem_2 *msg_2;
  399. msg_2 = msg_ptr[1]->data;
  400. error_code = msg_2->error_code;
  401. }
  402. if (command_id == DFGM_FREE_BUFF) {
  403. send_processing_info_gstmessage(self, "ipp-stop-processing");
  404. du_port_t *p = base->ports[1];
  405. struct td_buffer *tb;
  406. #ifdef OVERWRITE_INPUT_BUFFER
  407. if (self->nr_algos & 0x01) {
  408. /* so, output has ended up in input */
  409. /* expect to find input buffer ref here */
  410. g_assert(self->in_buf_ptr->user_data);
  411. /* hand it over to the output, which should have no ref there,
  412. * output_loop will pick it up and push downstream */
  413. g_assert(self->out_buf_ptr->user_data == NULL);
  414. self->out_buf_ptr->user_data = self->in_buf_ptr->user_data;
  415. self->in_buf_ptr->user_data = NULL;
  416. /* arrange for output_loop to send it back to us at once */
  417. self->out_buf_ptr->pinned = FALSE;
  418. tb = self->out_buf_ptr;
  419. }
  420. #endif
  421. tb = self->out_buf_ptr;
  422. tb->data->len = base->output_buffer_size;
  423. async_queue_push(p->queue, tb);
  424. /* push buffer into input queue */
  425. p = base->ports[0];
  426. tb = self->in_buf_ptr;
  427. /* NOTE needed, but does not go well with overwrite input */
  428. if (tb->user_data) {
  429. gst_buffer_unref(tb->user_data);
  430. tb->user_data = NULL;
  431. }
  432. async_queue_push(p->queue, tb);
  433. /* keep possible intermediate buffer around for re-use */
  434. /* signal processing finished */
  435. g_sem_up(self->sync_sem);
  436. }
  437. switch (command_id) {
  438. case DFGM_CREATE_XBF_ACK:
  439. case DFGM_CREATE_XBF_PIPE_ACK:
  440. case DFGM_DESTROY_XBF_ACK:
  441. case DFGM_SET_XBF_ALGS_ACK:
  442. case DFGM_STOP_PROCESSING_ACK:
  443. case DFGM_CLEAR_XBF_ALGS_ACK:
  444. case DFGM_DESTROY_XBF_PIPE_ACK:
  445. case DFGM_START_PROCESSING_ACK:
  446. case DFGM_FREE_BUFF:
  447. case DFGM_CONTROL_PIPE_ACK:
  448. case DFGM_FLUSH_PIPE_ACK:
  449. free_message_args(self);
  450. break;
  451. case DFGM_EVENT_ERROR:
  452. free_message_args(self);
  453. gstdsp_got_error(base, -1, "DFGM Event Error");
  454. base->done = TRUE;
  455. break;
  456. default:
  457. pr_warning(self, "unhandled command 0x%x", command_id);
  458. break;
  459. }
  460. switch (error_code) {
  461. case DFGM_ERROR_NONE:
  462. break;
  463. case DFGM_ERROR_CONTROL_PIPE:
  464. case DFGM_ERROR_QUEUE_BUFF:
  465. case DFGM_ERROR_CREATE_XBF_PIPE:
  466. case DFGM_ERROR_SET_ALGS:
  467. case DFGM_ERROR_CREATE_XBF:
  468. gstdsp_got_error(base, 0, "DFGM algo error");
  469. base->done = TRUE;
  470. break;
  471. default:
  472. gstdsp_got_error(base, 0, "DFGM unhandled error");
  473. base->done = TRUE;
  474. break;
  475. }
  476. g_sem_up(self->msg_sem);
  477. }
  478. static bool send_msg(GstDspIpp *self, int id,
  479. dmm_buffer_t *arg1,
  480. dmm_buffer_t *arg2,
  481. dmm_buffer_t *arg3)
  482. {
  483. GstDspBase *base = GST_DSP_BASE(self);
  484. if (!g_sem_down_timed(self->msg_sem, IPP_TIMEOUT)) {
  485. pr_err(self, "ipp send msg timed out");
  486. return false;
  487. }
  488. self->msg_ptr[0] = arg1;
  489. self->msg_ptr[1] = arg2;
  490. self->msg_ptr[2] = arg3;
  491. ipp_buffer_begin(self);
  492. if (id == DFGM_QUEUE_BUFF)
  493. send_processing_info_gstmessage(self, "ipp-start-processing");
  494. return dsp_send_message(base->dsp_handle, base->node, id,
  495. arg1 ? (uint32_t)arg1->map : 0,
  496. arg2 ? (uint32_t)arg2->map : 0);
  497. }
  498. static dmm_buffer_t *get_msg_2(GstDspIpp *self)
  499. {
  500. struct xbf_msg_elem_2 *msg_2;
  501. dmm_buffer_t *tmp;
  502. tmp = ipp_calloc(self, sizeof(*msg_2), DMA_BIDIRECTIONAL);
  503. msg_2 = tmp->data;
  504. msg_2->size = sizeof(*msg_2);
  505. dmm_buffer_map(tmp);
  506. return tmp;
  507. }
  508. struct create_xbf_msg_elem_1 {
  509. uint32_t size;
  510. uint32_t plat_fxns_string;
  511. uint32_t string_size;
  512. uint32_t plat_prms_ptr;
  513. };
  514. static bool create_xbf(GstDspIpp *self)
  515. {
  516. struct create_xbf_msg_elem_1 *create_xbf_msg1;
  517. dmm_buffer_t *b_arg_1;
  518. dmm_buffer_t *b_plat_fxn_string;
  519. const struct ipp_name_string plat_fxns_name = {
  520. .str = "IPPPLATFORMFXNS",
  521. .size = sizeof("IPPPLATFORMFXNS"),
  522. };
  523. b_plat_fxn_string = ipp_calloc(self, plat_fxns_name.size, DMA_TO_DEVICE);
  524. memcpy(b_plat_fxn_string->data, plat_fxns_name.str, plat_fxns_name.size);
  525. dmm_buffer_map(b_plat_fxn_string);
  526. b_arg_1 = ipp_calloc(self, sizeof(*create_xbf_msg1), DMA_BIDIRECTIONAL);
  527. create_xbf_msg1 = b_arg_1->data;
  528. create_xbf_msg1->size = sizeof(*create_xbf_msg1);
  529. create_xbf_msg1->plat_fxns_string = (uint32_t)b_plat_fxn_string->map;
  530. create_xbf_msg1->string_size = plat_fxns_name.size;
  531. dmm_buffer_map(b_arg_1);
  532. return send_msg(self, DFGM_CREATE_XBF, b_arg_1, get_msg_2(self), b_plat_fxn_string);
  533. }
  534. struct set_xbf_algs_msg_elem_1 {
  535. uint32_t size;
  536. uint32_t num_algs;
  537. struct set_xbf_algs_msg_elem_1_elem {
  538. uint32_t fxn_name_ptr;
  539. uint32_t fxn_name_size;
  540. uint32_t dma_name_ptr;
  541. uint32_t dma_name_size;
  542. } alg_tables[MAX_ALGS];
  543. };
  544. struct set_xbf_algs_msg_elem_2 {
  545. uint32_t size;
  546. uint32_t error_code;
  547. uint32_t mem_int_array_ptr;
  548. };
  549. static dmm_buffer_t *str_to_ipp_str(GstDspIpp *self, const char *s)
  550. {
  551. struct ipp_name_string *ipp_s;
  552. dmm_buffer_t *tmp;
  553. tmp = ipp_calloc(self, sizeof(*ipp_s), DMA_BIDIRECTIONAL);
  554. ipp_s = tmp->data;
  555. ipp_s->size = strlen(s);
  556. memcpy(ipp_s->str, s, ipp_s->size);
  557. dmm_buffer_map(tmp);
  558. tmp->len = ipp_s->size;
  559. return tmp;
  560. }
  561. static bool set_algorithm(GstDspIpp *self)
  562. {
  563. int nr_algos = self->nr_algos;
  564. struct set_xbf_algs_msg_elem_1 *msg_elem_1;
  565. struct set_xbf_algs_msg_elem_2 *msg_elem_2;
  566. dmm_buffer_t *b_arg_1;
  567. dmm_buffer_t *b_arg_2;
  568. int i;
  569. b_arg_1 = ipp_calloc(self, sizeof(*msg_elem_1), DMA_BIDIRECTIONAL);
  570. msg_elem_1 = b_arg_1->data;
  571. msg_elem_1->size = sizeof(*msg_elem_1);
  572. msg_elem_1->num_algs = nr_algos;
  573. b_arg_2 = ipp_calloc(self, sizeof(*msg_elem_2), DMA_BIDIRECTIONAL);
  574. msg_elem_2 = b_arg_2->data;
  575. msg_elem_2->size = sizeof(*msg_elem_2);
  576. dmm_buffer_map(b_arg_2);
  577. for (i = 0; i < nr_algos; i++) {
  578. struct set_xbf_algs_msg_elem_1_elem *e;
  579. struct ipp_algo *algo = self->algos[i];
  580. dmm_buffer_t *str;
  581. e = &msg_elem_1->alg_tables[i];
  582. if (algo->fxn) {
  583. str = str_to_ipp_str(self, algo->fxn);
  584. algo->b_algo_fxn = str;
  585. e->fxn_name_ptr = (uint32_t)str->map;
  586. e->fxn_name_size = str->len;
  587. }
  588. if (algo->dma_fxn) {
  589. str = str_to_ipp_str(self, algo->dma_fxn);
  590. algo->b_dma_fxn = str;
  591. e->dma_name_ptr = (uint32_t)str->map;
  592. e->dma_name_size = str->len;
  593. }
  594. }
  595. dmm_buffer_map(b_arg_1);
  596. return send_msg(self, DFGM_SET_XBF_ALGS, b_arg_1, b_arg_2, NULL);
  597. }
  598. struct filter_graph_edge {
  599. int32_t n[MAX_ALGS];
  600. };
  601. struct filter_graph {
  602. struct filter_graph_edge graph_connection[MAX_ALGS][MAX_ALGS];
  603. struct filter_graph_edge output_buf_distribution[MAX_ALGS];
  604. };
  605. static void prepare_filter_graph(GstDspIpp *self)
  606. {
  607. int32_t length;
  608. int32_t *ptr;
  609. int nr_algos = self->nr_algos;
  610. struct filter_graph *flt_graph;
  611. int i;
  612. int port = 1;
  613. self->flt_graph = ipp_calloc(self, sizeof(*flt_graph), DMA_TO_DEVICE);
  614. flt_graph = self->flt_graph->data;
  615. ptr = (int32_t *) flt_graph;
  616. length = sizeof(*flt_graph) / sizeof(int32_t);
  617. /* init graph to -1 */
  618. for (i = 0; i < length; i++)
  619. ptr[i] = -1;
  620. for (i = 0; i < nr_algos - 1; i++)
  621. *flt_graph->graph_connection[i][i + 1].n = 0;
  622. #ifdef OVERWRITE_INPUT_BUFFER
  623. /*
  624. * Star ports:
  625. * 0: input
  626. * 1: output
  627. *
  628. * Input buffer is also used for processing.Use above ports alternatively,
  629. * and the first one should always be 1.
  630. */
  631. for (i = 0; i < nr_algos - 1; i++) {
  632. *flt_graph->output_buf_distribution[i + 1].n = port;
  633. port = !port;
  634. }
  635. #else
  636. /*
  637. * Star ports:
  638. * 1: output
  639. * 2: intermediate
  640. *
  641. * Use these alternatively, and the last one in the pipeline should
  642. * always be 1.
  643. */
  644. for (i = nr_algos - 1; i >= 1; i--) {
  645. *flt_graph->output_buf_distribution[i].n = port;
  646. port = !(port - 1) + 1;
  647. }
  648. #endif
  649. dmm_buffer_map(self->flt_graph);
  650. }
  651. struct create_xbf_pipe_msg_elem_1 {
  652. uint32_t size;
  653. uint32_t filter_graph_ptr;
  654. uint32_t intrmd_bufs_array_ptr;
  655. uint32_t platform_params_ptr;
  656. uint32_t num_platform_params;
  657. uint32_t create_params_array_ptr;
  658. uint32_t num_create_params;
  659. uint32_t num_in_port;
  660. uint32_t num_out_port;
  661. };
  662. static bool create_pipe(GstDspIpp *self)
  663. {
  664. struct create_xbf_pipe_msg_elem_1 *arg_1;
  665. dmm_buffer_t *b_arg_1;
  666. dmm_buffer_t *b_create_params;
  667. int32_t *create_params_ptr_array;
  668. int i;
  669. int nr_algos = self->nr_algos;
  670. b_create_params = ipp_calloc(self, sizeof(int32_t) * nr_algos, DMA_TO_DEVICE);
  671. create_params_ptr_array = b_create_params->data;
  672. for (i = 0; i < nr_algos; i++)
  673. create_params_ptr_array[i] = (int32_t)self->algos[i]->create_params->map;
  674. dmm_buffer_map(b_create_params);
  675. b_arg_1 = ipp_calloc(self, sizeof(*arg_1), DMA_BIDIRECTIONAL);
  676. arg_1 = b_arg_1->data;
  677. arg_1->size = sizeof(*arg_1);
  678. arg_1->filter_graph_ptr = (uint32_t)self->flt_graph->map;
  679. arg_1->create_params_array_ptr = (uint32_t)b_create_params->map;
  680. arg_1->num_create_params = nr_algos;
  681. #ifdef OVERWRITE_INPUT_BUFFER
  682. arg_1->num_in_port = 2;
  683. #else
  684. arg_1->num_in_port = (nr_algos == 2) ? 2 : 3;
  685. #endif
  686. dmm_buffer_map(b_arg_1);
  687. return send_msg(self, DFGM_CREATE_XBF_PIPE, b_arg_1, get_msg_2(self), b_create_params);
  688. }
  689. static bool start_processing(GstDspIpp *self)
  690. {
  691. return send_msg(self, DFGM_START_PROCESSING, NULL, get_msg_2(self), NULL);
  692. }
  693. struct flush_pipe_msg_elem_1 {
  694. uint32_t size;
  695. uint32_t content_type;
  696. uint32_t num_buffer_port;
  697. uint32_t num_arg_port;
  698. };
  699. static bool flush_pipe(GstDspIpp *self, int content_type)
  700. {
  701. struct flush_pipe_msg_elem_1 *msg_1;
  702. dmm_buffer_t *b_arg_1;
  703. b_arg_1 = ipp_calloc(self, sizeof(*msg_1), DMA_TO_DEVICE);
  704. msg_1 = b_arg_1->data;
  705. msg_1->size = sizeof(*msg_1);
  706. msg_1->content_type = content_type;
  707. msg_1->num_buffer_port = -1;
  708. msg_1->num_arg_port = -1;
  709. dmm_buffer_map(b_arg_1);
  710. return send_msg(self, DFGM_FLUSH_PIPE, b_arg_1, get_msg_2(self), NULL);
  711. }
  712. static bool flush_queue_buffer(GstDspIpp *self)
  713. {
  714. bool ok;
  715. ok = flush_pipe(self, CONTENT_TYPE_BUFFER);
  716. if (!ok)
  717. return ok;
  718. ok = flush_pipe(self, CONTENT_TYPE_IN_ARGS);
  719. if (!ok)
  720. return ok;
  721. ok = flush_pipe(self, CONTENT_TYPE_OUT_ARGS);
  722. if (!ok)
  723. return ok;
  724. return TRUE;
  725. }
  726. struct control_pipe_msg_elem_1 {
  727. uint32_t size;
  728. struct {
  729. uint32_t alg_inst;
  730. uint32_t control_cmd;
  731. uint32_t dyn_params_ptr;
  732. uint32_t status_ptr;
  733. } control_tables[MAX_ALGS];
  734. };
  735. struct control_pipe_msg_elem_2 {
  736. uint32_t size;
  737. uint32_t error_code;
  738. struct {
  739. uint32_t command_error_code;
  740. } error_tables[MAX_ALGS];
  741. };
  742. static bool control_pipe(GstDspIpp *self)
  743. {
  744. struct control_pipe_msg_elem_1 *msg_1;
  745. struct control_pipe_msg_elem_2 *msg_2;
  746. dmm_buffer_t *b_msg_1;
  747. dmm_buffer_t *b_msg_2;
  748. size_t tbl_size;
  749. int i;
  750. int eenf_idx;
  751. int nr_algos = self->nr_algos;
  752. /*
  753. * If the input format is YUV420p, YUV422i to YUV420p conversion
  754. * algorithm will not present in the ipp pipeline. In that case
  755. * position of eenf in the pipeline is 2. Otherwise eenf positiom is 3.
  756. */
  757. if (self->in_pix_fmt == INTERNAL_FORMAT)
  758. eenf_idx = 2;
  759. else
  760. eenf_idx = 3;
  761. b_msg_1 = ipp_calloc(self, sizeof(*msg_1), DMA_TO_DEVICE);
  762. msg_1 = b_msg_1->data;
  763. tbl_size = (sizeof(msg_1->control_tables) / MAX_ALGS) * nr_algos;
  764. msg_1->size = sizeof(uint32_t) + tbl_size;
  765. for (i = 0; i < nr_algos; i++) {
  766. msg_1->control_tables[i].alg_inst = i;
  767. msg_1->control_tables[i].control_cmd = -1;
  768. if (i == eenf_idx) {
  769. msg_1->control_tables[i].control_cmd = 1;
  770. msg_1->control_tables[i].dyn_params_ptr = (uint32_t)self->dyn_params->map;
  771. msg_1->control_tables[i].status_ptr = (uint32_t)self->status_params->map;
  772. }
  773. }
  774. dmm_buffer_map(b_msg_1);
  775. b_msg_2 = ipp_calloc(self, sizeof(*msg_2), DMA_BIDIRECTIONAL);
  776. msg_2 = b_msg_2->data;
  777. tbl_size = (sizeof(msg_2->error_tables) / MAX_ALGS) * nr_algos;
  778. msg_2->size = 2 * sizeof(uint32_t) + tbl_size;
  779. dmm_buffer_map(b_msg_2);
  780. return send_msg(self, DFGM_CONTROL_PIPE, b_msg_1, b_msg_2, NULL);
  781. }
  782. struct queue_buff_msg_elem_1 {
  783. uint32_t size;
  784. uint32_t content_type;
  785. uint32_t port_num;
  786. uint32_t algo_index;
  787. uint32_t content_ptr;
  788. uint32_t reuse_allowed_flag;
  789. uint32_t content_size_used;
  790. uint32_t content_size;
  791. uint32_t process_status;
  792. uint32_t next_content_ptr;
  793. };
  794. static bool queue_buffer(GstDspIpp *self, struct td_buffer *tb, struct td_buffer *otb)
  795. {
  796. GstDspBase *base = GST_DSP_BASE(self);
  797. struct queue_buff_msg_elem_1 *queue_msg1;
  798. struct queue_buff_msg_elem_1 *msg_elem_list;
  799. dmm_buffer_t *msg_elem_array;
  800. int32_t cur_idx = 0;
  801. int i = 0;
  802. int nr_algos = self->nr_algos;
  803. int nr_buffers;
  804. int nr_msgs;
  805. #ifdef OVERWRITE_INPUT_BUFFER
  806. nr_buffers = 2;
  807. #else
  808. nr_buffers = (nr_algos == 2) ? 2 : 3;
  809. #endif
  810. nr_msgs = nr_algos * 2 + nr_buffers;
  811. msg_elem_array = ipp_calloc(self, nr_msgs * sizeof(*msg_elem_list), DMA_BIDIRECTIONAL);
  812. msg_elem_list = msg_elem_array->data;
  813. dmm_buffer_map(msg_elem_array);
  814. queue_msg1 = &msg_elem_list[cur_idx];
  815. for (i = 0; i < nr_buffers; i++) {
  816. queue_msg1->size = sizeof(*queue_msg1);
  817. queue_msg1->content_type = CONTENT_TYPE_BUFFER;
  818. queue_msg1->port_num = i;
  819. queue_msg1->reuse_allowed_flag = 0;
  820. if (i == 0) {
  821. self->in_buf_ptr = tb;
  822. queue_msg1->content_size_used = base->input_buffer_size;
  823. queue_msg1->content_size = base->input_buffer_size;
  824. queue_msg1->content_ptr = (uint32_t)tb->data->map;
  825. } else if (i == 1) {
  826. dmm_buffer_map(otb->data);
  827. self->out_buf_ptr = otb;
  828. queue_msg1->content_size_used = base->output_buffer_size;
  829. queue_msg1->content_size = base->output_buffer_size;
  830. queue_msg1->content_ptr = (uint32_t)self->out_buf_ptr->data->map;
  831. } else {
  832. dmm_buffer_t *b = NULL;
  833. if (self->intermediate_buf) {
  834. if (self->intermediate_buf->size >= base->input_buffer_size) {
  835. pr_debug(self, "re-using intermediate buffer");
  836. b = self->intermediate_buf;
  837. } else
  838. dmm_buffer_free(self->intermediate_buf);
  839. }
  840. if (!b) {
  841. pr_debug(self, "setting up intermediate buffer");
  842. b = ipp_calloc(self, base->input_buffer_size, DMA_FROM_DEVICE);
  843. dmm_buffer_map(b);
  844. self->intermediate_buf = b;
  845. }
  846. queue_msg1->content_size_used = base->input_buffer_size;
  847. queue_msg1->content_size = base->input_buffer_size;
  848. queue_msg1->content_ptr = (uint32_t)b->map;
  849. }
  850. cur_idx++;
  851. queue_msg1->next_content_ptr = (uint32_t)((char *)msg_elem_array->map) +
  852. (cur_idx)*sizeof(*msg_elem_list);
  853. queue_msg1 = &msg_elem_list[cur_idx];
  854. }
  855. for (i = 0; i < nr_algos; i++) {
  856. queue_msg1->size = sizeof(*queue_msg1);
  857. queue_msg1->content_type = CONTENT_TYPE_IN_ARGS;
  858. queue_msg1->algo_index = i;
  859. queue_msg1->content_size_used = self->algos[i]->in->len;
  860. queue_msg1->content_size = queue_msg1->content_size_used;
  861. queue_msg1->content_ptr = (uint32_t)self->algos[i]->in->map;
  862. cur_idx++;
  863. queue_msg1->next_content_ptr = (uint32_t)((char *)msg_elem_array->map) +
  864. (cur_idx)*sizeof(*msg_elem_list);
  865. queue_msg1 = &msg_elem_list[cur_idx];
  866. }
  867. for (i = 0; i < nr_algos; i++) {
  868. queue_msg1->size = sizeof(*queue_msg1);
  869. queue_msg1->content_type = CONTENT_TYPE_OUT_ARGS;
  870. queue_msg1->algo_index = i;
  871. queue_msg1->content_size_used = self->algos[i]->out->len;
  872. queue_msg1->content_size = queue_msg1->content_size_used;
  873. queue_msg1->content_ptr = (uint32_t)self->algos[i]->out->map;
  874. cur_idx++;
  875. if (i == nr_algos - 1) {
  876. queue_msg1->next_content_ptr = 0;
  877. } else {
  878. queue_msg1->next_content_ptr = (uint32_t)((char *)msg_elem_array->map) +
  879. (cur_idx)*sizeof(*msg_elem_list);
  880. queue_msg1 = &msg_elem_list[cur_idx];
  881. }
  882. }
  883. return send_msg(self, DFGM_QUEUE_BUFF, msg_elem_array, NULL, NULL);
  884. }
  885. struct stop_processing_msg_elem_1 {
  886. uint32_t size;
  887. uint32_t reset_state;
  888. };
  889. static bool stop_processing(GstDspIpp *self)
  890. {
  891. struct stop_processing_msg_elem_1 *arg_1;
  892. dmm_buffer_t *b_arg_1;
  893. b_arg_1 = ipp_calloc(self, sizeof(*arg_1), DMA_BIDIRECTIONAL);
  894. arg_1 = b_arg_1->data;
  895. arg_1->size = sizeof(*arg_1);
  896. arg_1->reset_state = 1;
  897. dmm_buffer_map(b_arg_1);
  898. return send_msg(self, DFGM_STOP_PROCESSING, b_arg_1, get_msg_2(self), NULL);
  899. }
  900. static bool destroy_pipe(GstDspIpp *self)
  901. {
  902. return send_msg(self, DFGM_DESTROY_XBF_PIPE, NULL, get_msg_2(self), NULL);
  903. }
  904. static bool clear_algorithm(GstDspIpp *self)
  905. {
  906. return send_msg(self, DFGM_CLEAR_XBF_ALGS, NULL, get_msg_2(self), NULL);
  907. }
  908. struct destroy_xbf_msg_elem_1 {
  909. uint32_t size;
  910. uint32_t plat_prms_ptr;
  911. };
  912. static bool destroy_xbf(GstDspIpp *self)
  913. {
  914. struct destroy_xbf_msg_elem_1 *arg_1;
  915. dmm_buffer_t *b_arg_1;
  916. b_arg_1 = ipp_calloc(self, sizeof(*arg_1), DMA_BIDIRECTIONAL);
  917. arg_1 = b_arg_1->data;
  918. arg_1->size = sizeof(*arg_1);
  919. dmm_buffer_map(b_arg_1);
  920. return send_msg(self, DFGM_DESTROY_XBF, b_arg_1, get_msg_2(self), NULL);
  921. }
  922. static bool init_pipe(GstDspBase *base)
  923. {
  924. GstDspIpp *self = GST_DSP_IPP(base);
  925. bool ok;
  926. ok = create_xbf(self);
  927. if (!ok)
  928. goto leave;
  929. ok = set_algorithm(self);
  930. if (!ok)
  931. goto leave;
  932. prepare_filter_graph(self);
  933. ok = create_pipe(self);
  934. if (!ok)
  935. goto leave;
  936. ok = start_processing(self);
  937. if (!ok)
  938. goto leave;
  939. leave:
  940. return ok;
  941. }
  942. /* Dynamic parameters for eenf */
  943. struct algo_buf_info {
  944. uint32_t min_num_in_bufs;
  945. uint32_t min_num_out_bufs;
  946. uint32_t min_in_buf_size[MAX_ALGS];
  947. uint32_t min_out_buf_size[MAX_ALGS];
  948. };
  949. struct algo_status {
  950. uint32_t status;
  951. uint32_t extended_error;
  952. struct algo_buf_info bufInfo;
  953. };
  954. static struct ipp_eenf_params eenf_normal = {
  955. .edge_enhancement_strength = 110,
  956. .weak_edge_threshold = 30,
  957. .strong_edge_threshold = 90,
  958. .low_freq_luma_noise_filter_strength = 7,
  959. .mid_freq_luma_noise_filter_strength = 14,
  960. .high_freq_luma_noise_filter_strength = 28,
  961. .low_freq_cb_noise_filter_strength = 8,
  962. .mid_freq_cb_noise_filter_strength = 16,
  963. .high_freq_cb_noise_filter_strength = 32,
  964. .low_freq_cr_noise_filter_strength = 8,
  965. .mid_freq_cr_noise_filter_strength = 16,
  966. .high_freq_cr_noise_filter_strength = 32,
  967. .shading_vert_param_1 = 10,
  968. .shading_vert_param_2 = 400,
  969. .shading_horz_param_1 = 10,
  970. .shading_horz_param_2 = 400,
  971. .shading_gain_scale = 128,
  972. .shading_gain_offset = 2048,
  973. .shading_gain_max_value = 16384,
  974. .ratio_downsample_cb_cr = 1,
  975. };
  976. static struct ipp_eenf_params eenf_aggressive = {
  977. .edge_enhancement_strength = 170,
  978. .weak_edge_threshold = 50,
  979. .strong_edge_threshold = 300,
  980. .low_freq_luma_noise_filter_strength = 30,
  981. .mid_freq_luma_noise_filter_strength = 80,
  982. .high_freq_luma_noise_filter_strength = 20,
  983. .low_freq_cb_noise_filter_strength = 60,
  984. .mid_freq_cb_noise_filter_strength = 40,
  985. .high_freq_cb_noise_filter_strength = 30,
  986. .low_freq_cr_noise_filter_strength = 50,
  987. .mid_freq_cr_noise_filter_strength = 30,
  988. .high_freq_cr_noise_filter_strength = 20,
  989. .shading_vert_param_1 = 1,
  990. .shading_vert_param_2 = 800,
  991. .shading_horz_param_1 = 1,
  992. .shading_horz_param_2 = 800,
  993. .shading_gain_scale = 128,
  994. .shading_gain_offset = 4096,
  995. .shading_gain_max_value = 32767,
  996. .ratio_downsample_cb_cr = 4,
  997. };
  998. static void
  999. get_eenf_dyn_params(GstDspIpp *self)
  1000. {
  1001. dmm_buffer_t *tmp;
  1002. size_t size;
  1003. struct ipp_eenf_params *params;
  1004. switch (self->eenf_strength) {
  1005. case NOISE_FILTER_CUSTOM:
  1006. pr_debug(self, "custom noise filter parameters");
  1007. params = &self->eenf_params;
  1008. break;
  1009. case NOISE_FILTER_NORMAL:
  1010. pr_debug(self, "normal noise filter parameters");
  1011. params = &eenf_normal;
  1012. break;
  1013. case NOISE_FILTER_AGGRESSIVE:
  1014. pr_debug(self, "aggerssive noise filter parameters");
  1015. params = &eenf_aggressive;
  1016. break;
  1017. default:
  1018. return;
  1019. }
  1020. params->size = sizeof(*params);
  1021. params->in_place = 0;
  1022. if (self->dyn_params) {
  1023. dmm_buffer_free(self->dyn_params);
  1024. self->dyn_params = NULL;
  1025. }
  1026. if (self->status_params) {
  1027. dmm_buffer_free(self->status_params);
  1028. self->status_params = NULL;
  1029. }
  1030. tmp = ipp_calloc(self, sizeof(*params), DMA_TO_DEVICE);
  1031. memcpy(tmp->data, params, sizeof(*params));
  1032. dmm_buffer_map(tmp);
  1033. self->dyn_params = tmp;
  1034. size = sizeof(struct algo_status);
  1035. self->status_params = ipp_calloc(self, size, DMA_BIDIRECTIONAL);
  1036. dmm_buffer_map(self->status_params);
  1037. }
  1038. static GstFlowReturn send_buffer(GstDspBase *base, struct td_buffer *tb)
  1039. {
  1040. GstDspIpp *self = GST_DSP_IPP(base);
  1041. bool ok;
  1042. struct td_buffer *otb;
  1043. /* no need to send output buffer to dsp */
  1044. if (tb->port->id == 1) {
  1045. /* in stead, we will do that later on, but for now queue it as available */
  1046. pr_debug(self, "collecting ipp output buffer %p", tb);
  1047. async_queue_push(self->ipp_queue, tb);
  1048. return true;
  1049. }
  1050. if (base->dsp_error)
  1051. return false;
  1052. /* need an output buffer */
  1053. otb = async_queue_pop(self->ipp_queue);
  1054. /* may have entered flushing state */
  1055. if (!otb) {
  1056. pr_debug(self, "could not obtain output buffer -> flushing");
  1057. /* do not lose this one */
  1058. if (tb->user_data) {
  1059. gst_buffer_unref(tb->user_data);
  1060. tb->user_data = NULL;
  1061. }
  1062. async_queue_push(base->ports[0]->queue, tb);
  1063. return GST_FLOW_WRONG_STATE;
  1064. }
  1065. pr_debug(self, "got ipp output buffer %p", otb);
  1066. send_processing_info_gstmessage(self, "ipp-start-init");
  1067. get_eenf_dyn_params(self);
  1068. ok = control_pipe(self);
  1069. if (!ok)
  1070. return GST_FLOW_ERROR;
  1071. dmm_buffer_map(tb->data);
  1072. self->sync_sem->count = 0;
  1073. ok = queue_buffer(GST_DSP_IPP(base), tb, otb);
  1074. if (!ok)
  1075. return GST_FLOW_ERROR;
  1076. ok = flush_queue_buffer(self);
  1077. if (!ok)
  1078. return GST_FLOW_ERROR;
  1079. /* wait until processing finished */
  1080. if (!g_sem_down_timed(self->sync_sem, IPP_TIMEOUT)) {
  1081. pr_err(self, "waiting for processing timed out");
  1082. return GST_FLOW_ERROR;
  1083. }
  1084. return GST_FLOW_OK;
  1085. }
  1086. static bool send_play_message(GstDspBase *base)
  1087. {
  1088. return true;
  1089. };
  1090. static void reset(GstDspBase *base)
  1091. {
  1092. GstDspIpp *self = GST_DSP_IPP(base);
  1093. self->msg_sem->count = 1;
  1094. for (unsigned i = 0; i < self->nr_algos; i++) {
  1095. struct ipp_algo *algo = self->algos[i];
  1096. if (!algo)
  1097. continue;
  1098. dmm_buffer_free(algo->create_params);
  1099. dmm_buffer_free(algo->b_algo_fxn);
  1100. dmm_buffer_free(algo->b_dma_fxn);
  1101. dmm_buffer_free(algo->in);
  1102. dmm_buffer_free(algo->out);
  1103. free(algo);
  1104. self->algos[i] = NULL;
  1105. }
  1106. dmm_buffer_free(self->flt_graph);
  1107. self->flt_graph = NULL;
  1108. dmm_buffer_free(self->intermediate_buf);
  1109. self->intermediate_buf = NULL;
  1110. dmm_buffer_free(self->dyn_params);
  1111. self->dyn_params = NULL;
  1112. dmm_buffer_free(self->status_params);
  1113. self->status_params = NULL;
  1114. async_queue_flush(self->ipp_queue);
  1115. }
  1116. static bool send_stop_message(GstDspBase *base)
  1117. {
  1118. GstDspIpp *self = GST_DSP_IPP(base);
  1119. bool ok = true;
  1120. if (base->dsp_error)
  1121. goto leave;
  1122. ok = stop_processing(self);
  1123. if (!ok)
  1124. goto leave;
  1125. ok = destroy_pipe(self);
  1126. if (!ok)
  1127. goto leave;
  1128. ok = clear_algorithm(self);
  1129. if (!ok)
  1130. goto leave;
  1131. ok = destroy_xbf(self);
  1132. if (!ok)
  1133. goto leave;
  1134. /* let's wait for the previous msg to complete */
  1135. if (!g_sem_down_timed(self->msg_sem, IPP_TIMEOUT)) {
  1136. pr_err(self, "ipp send msg timed out");
  1137. return false;
  1138. }
  1139. leave:
  1140. return ok;
  1141. }
  1142. static inline GstCaps *generate_sink_template(void)
  1143. {
  1144. GstCaps *caps;
  1145. GstStructure *struc;
  1146. caps = gst_caps_new_empty();
  1147. struc = gst_structure_new("video/x-raw-yuv", "format",
  1148. GST_TYPE_FOURCC, GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'), NULL);
  1149. gst_caps_append_structure(caps, struc);
  1150. #if SN_API > 0
  1151. struc = gst_structure_new("video/x-raw-yuv", "format",
  1152. GST_TYPE_FOURCC, GST_MAKE_FOURCC('I', '4', '2', '0'), NULL);
  1153. gst_caps_append_structure(caps, struc);
  1154. #endif
  1155. return caps;
  1156. }
  1157. static inline GstCaps *generate_src_template(void)
  1158. {
  1159. GstCaps *caps;
  1160. GstStructure *struc;
  1161. caps = gst_caps_new_empty();
  1162. struc = gst_structure_new("video/x-raw-yuv", "format",
  1163. GST_TYPE_FOURCC, GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'), NULL);
  1164. gst_caps_append_structure(caps, struc);
  1165. return caps;
  1166. }
  1167. static void *create_node(GstDspIpp *self)
  1168. {
  1169. GstDspBase *base;
  1170. int dsp_handle;
  1171. struct dsp_node *node = NULL;
  1172. const struct dsp_uuid dfgm_uuid = { 0xe57d1a99, 0xbc8d, 0x463c, 0xac, 0x93,
  1173. { 0x49, 0xeA, 0x1A, 0xC0, 0x19, 0x53 } };
  1174. struct dsp_node_attr_in attrs = {
  1175. .cb = sizeof(attrs),
  1176. .priority = 5,
  1177. .timeout = 1000,
  1178. };
  1179. base = GST_DSP_BASE(self);
  1180. dsp_handle = base->dsp_handle;
  1181. if (!gstdsp_register(dsp_handle, &dfgm_uuid, DSP_DCD_LIBRARYTYPE, "dfgm.dll64P")) {
  1182. pr_err(self, "failed to register usn node library");
  1183. return NULL;
  1184. }
  1185. if (!gstdsp_register(dsp_handle, base->codec->uuid, DSP_DCD_LIBRARYTYPE, base->codec->filename)) {
  1186. pr_err(self, "failed to register algo node library");
  1187. return NULL;
  1188. }
  1189. if (!gstdsp_register(dsp_handle, base->codec->uuid, DSP_DCD_NODETYPE, base->codec->filename)) {
  1190. pr_err(self, "failed to register algo node");
  1191. return NULL;
  1192. }
  1193. if (!dsp_node_allocate(dsp_handle, base->proc, base->codec->uuid, NULL, &attrs, &node)) {
  1194. pr_err(self, "dsp node allocate failed");
  1195. dsp_node_free(dsp_handle, node);
  1196. return NULL;
  1197. }
  1198. if (!dsp_node_create(dsp_handle, node)) {
  1199. pr_err(self, "dsp node create failed");
  1200. dsp_node_free(dsp_handle, node);
  1201. return NULL;
  1202. }
  1203. return node;
  1204. }
  1205. static gboolean sink_setcaps(GstPad *pad, GstCaps *caps)
  1206. {
  1207. GstDspIpp *self;
  1208. GstDspBase *base;
  1209. GstStructure *in_struc;
  1210. GstCaps *out_caps;
  1211. GstStructure *out_struc;
  1212. int width = 0;
  1213. int height = 0;
  1214. unsigned int format;
  1215. const GValue *framerate;
  1216. self = GST_DSP_IPP(GST_PAD_PARENT(pad));
  1217. base = GST_DSP_BASE(self);
  1218. in_struc = gst_caps_get_structure(caps, 0);
  1219. out_caps = gst_caps_new_empty();
  1220. out_struc = gst_structure_new("video/x-raw-yuv", NULL);
  1221. if (gst_structure_get_int(in_struc, "width", &width))
  1222. gst_structure_set(out_struc, "width", G_TYPE_INT, width, NULL);
  1223. if (gst_structure_get_int(in_struc, "height", &height))
  1224. gst_structure_set(out_struc, "height", G_TYPE_INT, height, NULL);
  1225. if (width > MAX_WIDTH || width & 0x0F) {
  1226. gstdsp_got_error(base, 0, "invalid width value");
  1227. return FALSE;
  1228. } else if (height > MAX_HEIGHT || height & 0x07) {
  1229. gstdsp_got_error(base, 0, "invalid height value");
  1230. return FALSE;
  1231. } else if (width * height > MAX_TOTAL_PIXEL) {
  1232. gstdsp_got_error(base, 0, "Total number of pixels exceeding the limit");
  1233. return FALSE;
  1234. }
  1235. if (gstdsp_need_node_reset(base, caps, self->width, self->height)) {
  1236. /* flush pending frames if needed */
  1237. if (base->flush_buffer) {
  1238. pr_debug(self, "flushing pending");
  1239. base->flush_buffer(base);
  1240. }
  1241. /* wait (some time) for all to have been pushed */
  1242. g_mutex_lock(base->ts_mutex);
  1243. while (base->ts_count > 0) {
  1244. GTimeVal tv = {1, 0};
  1245. if (!g_cond_timed_wait(base->ts_cond, base->ts_mutex, &tv)) {
  1246. pr_info(self, "timeout waiting for all buffers pushed");
  1247. break;
  1248. }
  1249. }
  1250. g_mutex_unlock(base->ts_mutex);
  1251. gstdsp_reinit(base);
  1252. }
  1253. if (base->node)
  1254. return TRUE;
  1255. gst_structure_get_fourcc(in_struc, "format", &format);
  1256. /* ipp output colour format is always UYVY */
  1257. gst_structure_set(out_struc, "format", GST_TYPE_FOURCC,
  1258. GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'), NULL);
  1259. framerate = gst_structure_get_value(in_struc, "framerate");
  1260. if (framerate)
  1261. gst_structure_set_value(out_struc, "framerate", framerate);
  1262. switch (format) {
  1263. case GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'):
  1264. self->in_pix_fmt = IPP_YUV_422ILE;
  1265. base->input_buffer_size = width * height * 2;
  1266. break;
  1267. case GST_MAKE_FOURCC('I', '4', '2', '0'):
  1268. self->in_pix_fmt = IPP_YUV_420P;
  1269. base->input_buffer_size = (width * height * 3) / 2;
  1270. break;
  1271. default:
  1272. pr_err(self, "unsupported colour format");
  1273. return FALSE;
  1274. }
  1275. base->output_buffer_size = width * height * 2;
  1276. self->width = width;
  1277. self->height = height;
  1278. gst_caps_append_structure(out_caps, out_struc);
  1279. if (!gst_pad_take_caps(base->srcpad, out_caps))
  1280. return FALSE;
  1281. du_port_alloc_buffers(base->ports[0], 1);
  1282. du_port_alloc_buffers(base->ports[1], 2);
  1283. base->node = create_node(self);
  1284. if (!base->node) {
  1285. pr_err(self, "dsp node creation failed");
  1286. return FALSE;
  1287. }
  1288. if (!setup_ipp_params(self))
  1289. return FALSE;
  1290. if (!gstdsp_start(base)) {
  1291. pr_err(self, "dsp start failed");
  1292. return FALSE;
  1293. }
  1294. if (!init_pipe(base))
  1295. return FALSE;
  1296. return true;
  1297. }
  1298. static gboolean sink_event(GstDspBase *base, GstEvent *event)
  1299. {
  1300. GstDspIpp *self = GST_DSP_IPP(base);
  1301. const GstStructure *structure;
  1302. structure = gst_event_get_structure(event);
  1303. if (!structure)
  1304. goto leave;
  1305. switch (GST_EVENT_TYPE(event)) {
  1306. case GST_EVENT_CUSTOM_DOWNSTREAM: {
  1307. unsigned tmp;
  1308. struct ipp_eenf_params *param = &self->eenf_params;
  1309. if (!gst_structure_has_name(structure, "application/x-gst-ipp"))
  1310. break;
  1311. pr_info(self, "custom eenf params received");
  1312. if (gst_structure_get_uint(structure, "edge-enhancement-strength", &tmp))
  1313. param->edge_enhancement_strength = tmp;
  1314. if (gst_structure_get_uint(structure, "weak-edge-threshold", &tmp))
  1315. param->weak_edge_threshold = tmp;
  1316. if (gst_structure_get_uint(structure, "strong-edge-threshold", &tmp))
  1317. param->strong_edge_threshold = tmp;
  1318. if (gst_structure_get_uint(structure, "luma-noise-filter-strength-low", &tmp))
  1319. param->low_freq_luma_noise_filter_strength = tmp;
  1320. if (gst_structure_get_uint(structure, "luma-noise-filter-strength-mid", &tmp))
  1321. param->mid_freq_luma_noise_filter_strength = tmp;
  1322. if (gst_structure_get_uint(structure, "luma-noise-filter-strength-high", &tmp))
  1323. param->high_freq_luma_noise_filter_strength = tmp;
  1324. if (gst_structure_get_uint(structure, "cb-noise-filter-strength-low", &tmp))
  1325. param->low_freq_cb_noise_filter_strength = tmp;
  1326. if (gst_structure_get_uint(structure, "cb-noise-filter-strength-mid", &tmp))
  1327. param->mid_freq_cb_noise_filter_strength = tmp;
  1328. if (gst_structure_get_uint(structure, "cb-noise-filter-strength-high", &tmp))
  1329. param->high_freq_cb_noise_filter_strength = tmp;
  1330. if (gst_structure_get_uint(structure, "cr-noise-filter-strength-low", &tmp))
  1331. param->low_freq_cr_noise_filter_strength = tmp;
  1332. if (gst_structure_get_uint(structure, "cr-noise-filter-strength-mid", &tmp))
  1333. param->mid_freq_cr_noise_filter_strength = tmp;
  1334. if (gst_structure_get_uint(structure, "cr-noise-filter-strength-high", &tmp))
  1335. param->high_freq_cr_noise_filter_strength = tmp;
  1336. if (gst_structure_get_uint(structure, "shading-vert-param1", &tmp))
  1337. param->shading_vert_param_1 = tmp;
  1338. if (gst_structure_get_uint(structure, "shading-vert-param2", &tmp))
  1339. param->shading_vert_param_2 = tmp;
  1340. if (gst_structure_get_uint(structure, "shading-horz-param1", &tmp))
  1341. param->shading_horz_param_1 = tmp;
  1342. if (gst_structure_get_uint(structure, "shading-horz-param2", &tmp))
  1343. param->shading_horz_param_2 = tmp;
  1344. if (gst_structure_get_uint(structure, "shading-gain-scale", &tmp))
  1345. param->shading_gain_scale = tmp;
  1346. if (gst_structure_get_uint(structure, "shading-gain-offset", &tmp))
  1347. param->shading_gain_offset = tmp;
  1348. if (gst_structure_get_uint(structure, "shading-gain-maxvalue", &tmp))
  1349. param->shading_gain_max_value = tmp;
  1350. if (gst_structure_get_uint(structure, "ratio-downsample-cb-cr", &tmp))
  1351. param->ratio_downsample_cb_cr = tmp;
  1352. gst_event_unref(event);
  1353. return true;
  1354. }
  1355. default:
  1356. break;
  1357. }
  1358. leave:
  1359. return parent_class->sink_event(base, event);
  1360. }
  1361. static GstCaps *getcaps(GstPad * pad)
  1362. {
  1363. GstDspBase *base = GST_DSP_BASE(GST_PAD_PARENT(pad));
  1364. GstPad *otherpad;
  1365. GstCaps *caps = NULL;
  1366. otherpad = (pad == base->srcpad) ? base->sinkpad : base->srcpad;
  1367. caps = gst_pad_peer_get_caps_reffed(otherpad);
  1368. if (caps) {
  1369. GstCaps *tmp_caps;
  1370. const GstCaps *pad_template_caps;
  1371. pad_template_caps = gst_pad_get_pad_template_caps(otherpad);
  1372. tmp_caps = gst_caps_intersect(caps, pad_template_caps);
  1373. gst_caps_unref(caps);
  1374. caps = tmp_caps;
  1375. pad_template_caps = gst_pad_get_pad_template_caps(pad);
  1376. tmp_caps = gst_caps_intersect(caps, pad_template_caps);
  1377. gst_caps_unref(caps);
  1378. caps = tmp_caps;
  1379. } else {
  1380. caps = gst_caps_copy(gst_pad_get_pad_template_caps(pad));
  1381. }
  1382. gchar *str = gst_caps_to_string(caps);
  1383. pr_debug(base, "returning caps: %s", str);
  1384. g_free(str);
  1385. return caps;
  1386. }
  1387. static void send_processing_info_gstmessage(GstDspIpp *self, const gchar* info)
  1388. {
  1389. GstStructure *s;
  1390. GstMessage *msg;
  1391. s = gst_structure_new(info, NULL);
  1392. msg = gst_message_new_element(GST_OBJECT(self), s);
  1393. pr_debug(self, "Sending message : %s", info);
  1394. if (gst_element_post_message(GST_ELEMENT(self), msg) == FALSE)
  1395. pr_warning(self, "Element has no bus, no message sent");
  1396. }
  1397. static void
  1398. set_property(GObject *obj,
  1399. guint prop_id,
  1400. const GValue *value,
  1401. GParamSpec *pspec)
  1402. {
  1403. GstDspIpp *self = GST_DSP_IPP(obj);
  1404. switch (prop_id) {
  1405. case PROP_NOISE_FILTER_STRENGTH:
  1406. self->eenf_strength = g_value_get_enum(value);
  1407. break;
  1408. default:
  1409. G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
  1410. break;
  1411. }
  1412. }
  1413. static void
  1414. get_property(GObject *obj,
  1415. guint prop_id,
  1416. GValue *value,
  1417. GParamSpec *pspec)
  1418. {
  1419. GstDspIpp *self = GST_DSP_IPP(obj);
  1420. switch (prop_id) {
  1421. case PROP_NOISE_FILTER_STRENGTH:
  1422. g_value_set_enum(value, self->eenf_strength);
  1423. break;
  1424. default:
  1425. G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
  1426. break;
  1427. }
  1428. }
  1429. struct td_codec ipp_codec = {
  1430. .uuid = &(const struct dsp_uuid) { 0x8ea1b508, 0x49be, 0x4cd0, 0xbb, 0x12,
  1431. { 0xea, 0x95, 0x00, 0x58, 0xb3, 0x6b } },
  1432. .filename = "ipp_sn.dll64P",
  1433. };
  1434. static void instance_init(GTypeInstance *instance, gpointer g_class)
  1435. {
  1436. GstDspBase *base = GST_DSP_BASE(instance);
  1437. GstDspIpp *self = GST_DSP_IPP(instance);
  1438. base->got_message = got_message;
  1439. base->send_buffer = send_buffer;
  1440. base->send_play_message = send_play_message;
  1441. base->send_stop_message = send_stop_message;
  1442. base->reset = reset;
  1443. self->msg_sem = g_sem_new(1);
  1444. self->sync_sem = g_sem_new(0);
  1445. self->ipp_queue = async_queue_new();
  1446. base->eos_timeout = 0;
  1447. base->use_pinned = TRUE;
  1448. base->codec = &ipp_codec;
  1449. /* initialize params to normal strength */
  1450. memcpy(&self->eenf_params, &eenf_normal, sizeof(eenf_normal));
  1451. gst_pad_set_setcaps_function(base->sinkpad, sink_setcaps);
  1452. gst_pad_set_getcaps_function(base->sinkpad, getcaps);
  1453. gst_pad_set_getcaps_function(base->srcpad, getcaps);
  1454. }
  1455. static void finalize(GObject *obj)
  1456. {
  1457. GstDspIpp *self = GST_DSP_IPP(obj);
  1458. g_sem_free(self->msg_sem);
  1459. g_sem_free(self->sync_sem);
  1460. async_queue_free(self->ipp_queue);
  1461. G_OBJECT_CLASS(parent_class)->finalize(obj);
  1462. }
  1463. static void class_init(gpointer g_class, gpointer class_data)
  1464. {
  1465. GObjectClass *gobject_class;
  1466. GstDspBaseClass *gstdspbase_class;
  1467. gobject_class = G_OBJECT_CLASS(g_class);
  1468. gstdspbase_class = GST_DSP_BASE_CLASS(g_class);
  1469. gobject_class->set_property = set_property;
  1470. gobject_class->get_property = get_property;
  1471. g_object_class_install_property(gobject_class, PROP_NOISE_FILTER_STRENGTH,
  1472. g_param_spec_enum("noise-filter-strength", "Noise filter strength",
  1473. "Specifies the strength of the noise filter",
  1474. GST_TYPE_IPP_NOISE_FILTER_STRENGTH,
  1475. DEFAULT_NOISE_FILTER_STRENGTH,
  1476. G_PARAM_READWRITE));
  1477. parent_class = g_type_class_peek_parent(g_class);
  1478. gobject_class->finalize = finalize;
  1479. gstdspbase_class->sink_event = sink_event;
  1480. }
  1481. static void base_init(gpointer g_class)
  1482. {
  1483. GstElementClass *element_class;
  1484. GstPadTemplate *template;
  1485. element_class = GST_ELEMENT_CLASS(g_class);
  1486. gst_element_class_set_details_simple(element_class,
  1487. "DSP IPP",
  1488. "Codec/Encoder/Image",
  1489. "Image processing algorithms",
  1490. "Texas Instruments");
  1491. template = gst_pad_template_new("src", GST_PAD_SRC,
  1492. GST_PAD_ALWAYS,
  1493. generate_src_template());
  1494. gst_element_class_add_pad_template(element_class, template);
  1495. gst_object_unref(template);
  1496. template = gst_pad_template_new("sink", GST_PAD_SINK,
  1497. GST_PAD_ALWAYS,
  1498. generate_sink_template());
  1499. gst_element_class_add_pad_template(element_class, template);
  1500. gst_object_unref(template);
  1501. }
  1502. GType gst_dsp_ipp_get_type(void)
  1503. {
  1504. static GType type;
  1505. if (G_UNLIKELY(type == 0)) {
  1506. GTypeInfo type_info = {
  1507. .class_size = sizeof(GstDspIppClass),
  1508. .base_init = base_init,
  1509. .class_init = class_init,
  1510. .instance_size = sizeof(GstDspIpp),
  1511. .instance_init = instance_init
  1512. };
  1513. type = g_type_register_static(GST_DSP_BASE_TYPE, "GstDspIpp", &type_info, 0);
  1514. }
  1515. return type;
  1516. }