gstdspipp.c 39 KB

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