pbu.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. // SPDX-License-Identifier: LGPL-2.1 OR BSD-3-Clause
  2. /*
  3. * Copyright (c) 2019, Chips&Media
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  16. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  19. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <stdio.h>
  27. #include <stdint.h>
  28. #include <stddef.h>
  29. #include "main_helper.h"
  30. #include "pbu.h"
  31. enum
  32. {
  33. SPP_IN,
  34. SPP_OUT_RBSP,
  35. SPP_OUT_NAL,
  36. SPP_UNALIGN
  37. };
  38. # define NAL_BUF_SIZE 512
  39. typedef struct
  40. {
  41. // stream buffer status
  42. unsigned char* rd_ptr;
  43. unsigned char* wr_ptr;
  44. unsigned char* bb_start;
  45. unsigned char* bb_end;
  46. int explicit_end_flag;
  47. int stream_end_flag;
  48. // instance handler ... for interrupt handling
  49. void* handle;
  50. } gbu_if_t;
  51. typedef struct
  52. {
  53. // for interfacing
  54. gbu_if_t *param;
  55. // internal read pointer
  56. Uint8* rd_ptr;
  57. // nal buffer things
  58. Uint8 nal_buf[2][NAL_BUF_SIZE];
  59. int nal_buf_idx;
  60. int nal_buf_cnt;
  61. int nal_ptr;
  62. Uint32 nal_cnt;
  63. int last_nal_byte;
  64. // rbsp buffer things
  65. Uint32 wbuf[2];
  66. Int8 wbuf_emul_info;
  67. Int8 bptr;
  68. Int8 rbsp_bit_cnt;
  69. int rbsp_init;
  70. // rbsp consumed bit count
  71. int tcnt;
  72. int tc;
  73. // trailing zero counter
  74. int zero_cnt;
  75. // eos
  76. int eos;
  77. Uint32 est_nal_byte_cnt;
  78. int epbRequired;
  79. } gbu_t;
  80. static void enc_flush_rbsp(spp_enc_context context);
  81. static void enc_flush_nal_buf(spp_enc_context context);
  82. static void put_bits(spp_enc_context context, Uint32 var, int n);
  83. static void put_ue(spp_enc_context context, Uint32 var);
  84. spp_enc_context spp_enc_init(Uint8 *buffer, int buffer_size, int enableEPB)
  85. {
  86. gbu_t* gbu;
  87. gbu = (gbu_t*)osal_malloc(sizeof(gbu_t));
  88. if (!gbu)
  89. return NULL;
  90. gbu->param = (gbu_if_t *)osal_malloc(sizeof(gbu_if_t));
  91. if (!gbu->param) {
  92. osal_free(gbu);
  93. return NULL;
  94. }
  95. // connect interface structure
  96. gbu->param->bb_start = buffer;
  97. gbu->param->bb_end = buffer + buffer_size;
  98. gbu->param->rd_ptr = buffer;
  99. gbu->param->wr_ptr = buffer;
  100. // reset write pointer
  101. gbu->rd_ptr = gbu->param->wr_ptr;
  102. // reset nal memory index/cnt
  103. gbu->nal_buf_idx = 0;
  104. gbu->nal_buf_cnt = 0;
  105. gbu->nal_ptr = 0;
  106. gbu->nal_cnt = 0;
  107. gbu->est_nal_byte_cnt = 0;
  108. // reset trailing zero count
  109. gbu->zero_cnt = 0;
  110. // reset rbsp consumed count
  111. gbu->bptr = 32;
  112. gbu->rbsp_bit_cnt = 0;
  113. gbu->tcnt = 0;
  114. // reset wbuf
  115. gbu->wbuf[0] = gbu->wbuf[1] = 0x00;
  116. gbu->epbRequired = enableEPB;
  117. return (spp_enc_context)gbu;
  118. }
  119. void spp_enc_deinit(spp_enc_context context)
  120. {
  121. gbu_t* gbu = (gbu_t *)context;
  122. if (gbu) {
  123. if (gbu->param) {
  124. osal_free(gbu->param);
  125. }
  126. osal_free(gbu);
  127. }
  128. }
  129. void spp_enc_init_rbsp(spp_enc_context context)
  130. {
  131. gbu_t* gbu = (gbu_t *)context;
  132. gbu->tcnt = 0;
  133. // reset trailing zero count
  134. gbu->zero_cnt = 0;
  135. // reset rbsp consumed count
  136. gbu->bptr = 32;
  137. // reset wbuf
  138. gbu->wbuf[0] = gbu->wbuf[1] = 0x00;
  139. }
  140. void spp_enc_put_nal_byte(spp_enc_context context, Uint32 var, int n)
  141. {
  142. int i;
  143. gbu_t* gbu = (gbu_t *)context;
  144. for (i = n-1 ; i >= 0 ; i--)
  145. {
  146. gbu->nal_buf[gbu->nal_buf_idx][gbu->nal_ptr] = ((var >> (i<<3)) & 0xFF);
  147. gbu->nal_ptr++;
  148. gbu->nal_cnt++;
  149. gbu->est_nal_byte_cnt++;
  150. if (gbu->nal_ptr == NAL_BUF_SIZE)
  151. {
  152. enc_flush_nal_buf(context);
  153. gbu->nal_buf_idx = (gbu->nal_buf_idx+1)&1;
  154. gbu->nal_ptr = 0;
  155. }
  156. }
  157. }
  158. void spp_enc_put_bits(spp_enc_context context, Uint32 var, int n)
  159. {
  160. Uint32 mask;
  161. Uint32 data;
  162. gbu_t* gbu = (gbu_t *)context;
  163. if (n == 0)
  164. return;
  165. // update total rbsp count
  166. gbu->tcnt += n;
  167. if (n > gbu->bptr)
  168. {
  169. // write data
  170. mask = (1 << gbu->bptr) - 1;
  171. data = (var >> (n - gbu->bptr)) & mask;
  172. gbu->wbuf[0] |= data;
  173. gbu->rbsp_bit_cnt += gbu->bptr;
  174. // update input data
  175. n -= gbu->bptr;
  176. // update gbu bptr
  177. gbu->bptr = 0;
  178. // write rbsp data to nbuf
  179. enc_flush_rbsp(context);
  180. }
  181. mask = ((Uint64)1 << n) - 1;
  182. data = var & mask;
  183. // write data
  184. gbu->wbuf[0] |= data << (gbu->bptr - n);
  185. gbu->rbsp_bit_cnt += n;
  186. // update bptr
  187. gbu->bptr -= n;
  188. if (gbu->bptr == 0)
  189. enc_flush_rbsp(context);
  190. }
  191. void spp_enc_flush(spp_enc_context context)
  192. {
  193. enc_flush_rbsp(context);
  194. enc_flush_nal_buf(context);
  195. }
  196. void enc_flush_rbsp(spp_enc_context context)
  197. {
  198. gbu_t* gbu = (gbu_t *)context;
  199. int cnt = (32 - gbu->bptr + 7) >> 3;
  200. int pos = 4 - cnt;
  201. Uint8 data;
  202. gbu->wbuf[1] = gbu->wbuf[0];
  203. for (cnt = cnt-1 ; cnt >= 0 ; cnt--)
  204. {
  205. data = (gbu->wbuf[0] >> ((cnt+pos)<<3)) & 0xFF;
  206. if (gbu->epbRequired == 1)
  207. {
  208. // insert EPB if needed
  209. if ((gbu->zero_cnt == 2) && (data <= 0x03))
  210. {
  211. spp_enc_put_nal_byte(context, 0x03, 1);
  212. gbu->zero_cnt = 0;
  213. }
  214. }
  215. spp_enc_put_nal_byte(context, data, 1);
  216. // update number of trailing zeroes
  217. if (data == 0x00)
  218. gbu->zero_cnt++;
  219. else
  220. gbu->zero_cnt = 0;
  221. }
  222. // reset bit ptr
  223. gbu->bptr = 32;
  224. // reset wbuf
  225. gbu->wbuf[0] = 0;
  226. }
  227. static void enc_flush_nal_buf(spp_enc_context context)
  228. {
  229. int i, cnt;
  230. int left, room;
  231. Uint8* ptr;
  232. Uint8* align_wr_ptr;
  233. gbu_t* gbu = (gbu_t *)context;
  234. gbu_if_t* io = gbu->param;
  235. ptr = (Uint8 *)io->wr_ptr;
  236. align_wr_ptr = (Uint8*)(ptr);
  237. for (cnt = 0 ; cnt < gbu->nal_ptr ; )
  238. {
  239. room = left = io->rd_ptr - io->wr_ptr;
  240. // wraparound case
  241. if (left <= 0)
  242. {
  243. left = io->bb_end - io->wr_ptr;
  244. room += io->bb_end - io->bb_start;
  245. }
  246. // write stream to CPB
  247. for (i = 0 ; i < left && cnt < gbu->nal_ptr ; i++, cnt++)
  248. *(align_wr_ptr + i) = gbu->nal_buf[gbu->nal_buf_idx][cnt];
  249. gbu->param->wr_ptr = align_wr_ptr + i;
  250. // handle wraparound case
  251. if (io->wr_ptr == io->bb_end)
  252. io->wr_ptr = io->bb_start;
  253. // if room is small enough, then flush data to external memory
  254. if ((room - i) < 256)
  255. {
  256. //host_isr(gbu->param, INT_BIT_BIT_BUF_FULL, NULL);
  257. continue;
  258. }
  259. }
  260. // clear nal_ptr
  261. gbu->nal_ptr = 0;
  262. }
  263. // put unsigned exp-golomb code
  264. void spp_enc_put_ue(spp_enc_context context, Uint32 var)
  265. {
  266. Int32 num;
  267. Uint32 data;
  268. num = -1;
  269. data = var + 1;
  270. while (data)
  271. {
  272. data = data >> 1;
  273. num++;
  274. }
  275. // leading zero bits
  276. put_bits(context, 0, num);
  277. put_bits(context, var+1, num+1);
  278. }
  279. Uint32 spp_enc_get_ue_bit_size(Uint32 var)
  280. {
  281. Uint32 size;
  282. Int32 num;
  283. Uint32 data;
  284. num = -1;
  285. data = var + 1;
  286. while (data)
  287. {
  288. data = data >> 1;
  289. num++;
  290. }
  291. // leading zero bits
  292. size = num;
  293. size += (num+1);
  294. return size;
  295. }
  296. // put signed exp-golomb code
  297. void spp_enc_put_se(spp_enc_context context, Int32 var)
  298. {
  299. Uint32 data;
  300. // (-1)^(code_num + 1)
  301. if (var > 0)
  302. data = (( var)<<1) - 1;
  303. else
  304. data = ((-var)<<1);
  305. put_ue(context, data);
  306. }
  307. // put stop one bit & padding zeroes
  308. void spp_enc_put_byte_align(spp_enc_context context, int has_stop_bit)
  309. {
  310. gbu_t* gbu = (gbu_t *)context;
  311. // stop one bit
  312. if (has_stop_bit)
  313. spp_enc_put_bits(context, 1, 1);
  314. // padding zeroes
  315. if (gbu->bptr & 7)
  316. spp_enc_put_bits(context, 0, gbu->bptr & 7);
  317. }
  318. // number of remain bit in wbuf
  319. Uint32 spp_enc_get_wbuf_remain(spp_enc_context context)
  320. {
  321. gbu_t* gbu = (gbu_t *)context;
  322. return (Uint32)gbu->bptr;
  323. }
  324. // number of total bit after gbu initialization
  325. Uint32 spp_enc_get_rbsp_bit(spp_enc_context context)
  326. {
  327. gbu_t* gbu = (gbu_t *)context;
  328. return (Uint32)gbu->tcnt;
  329. }
  330. // number of nal byte after gbu initialization
  331. Uint32 spp_enc_get_nal_cnt(spp_enc_context context)
  332. {
  333. gbu_t* gbu = (gbu_t *)context;
  334. return (Uint32)gbu->nal_cnt;
  335. }
  336. // return wr_ptr of stream buffer
  337. Uint8* spp_enc_get_wr_ptr(spp_enc_context context)
  338. {
  339. gbu_t* gbu = (gbu_t *)context;
  340. enc_flush_rbsp(context);
  341. enc_flush_nal_buf(context);
  342. return gbu->param->wr_ptr;
  343. }
  344. Uint8* spp_enc_get_wr_ptr_only(spp_enc_context context)
  345. {
  346. gbu_t* gbu = (gbu_t *)context;
  347. enc_flush_rbsp(context);
  348. return gbu->param->wr_ptr + gbu->nal_ptr;
  349. }
  350. void spp_enc_set_wr_ptr(spp_enc_context context, Uint32 wr_ptr)
  351. {
  352. gbu_t* gbu = (gbu_t *)context;
  353. gbu_if_t* io = gbu->param;
  354. intptr_t wr_int_ptr = wr_ptr;
  355. intptr_t bb_end_int_ptr = (intptr_t)io->bb_end;
  356. intptr_t gbu_param_bb_end_int_ptr = (intptr_t)gbu->param->bb_end;
  357. intptr_t gbu_param_bb_start_int_ptr = (intptr_t)gbu->param->bb_start;
  358. while(wr_ptr > bb_end_int_ptr)
  359. wr_int_ptr = wr_int_ptr + gbu_param_bb_end_int_ptr - gbu_param_bb_start_int_ptr;
  360. io->wr_ptr = (Uint8 *)wr_int_ptr;
  361. }
  362. // get a estimated NAL count in byte
  363. Uint32 spp_enc_get_est_nal_cnt(spp_enc_context context)
  364. {
  365. gbu_t* gbu = (gbu_t *)context;
  366. Uint32 est_nal_byte = 0;
  367. Uint8 data;
  368. Int32 cnt = (32 - gbu->bptr ) >> 3;
  369. Uint32 pos = 4 - cnt;
  370. Uint32 zero_cnt = gbu->zero_cnt;
  371. for (cnt = cnt-1 ; cnt >= 0 ; cnt--)
  372. {
  373. data = (gbu->wbuf[0] >> ((cnt+pos)<<3)) & 0xFF;
  374. // insert EPB if needed
  375. if ((zero_cnt == 2) && (data <= 0x03))
  376. {
  377. est_nal_byte++;
  378. zero_cnt = 0;
  379. }
  380. est_nal_byte++;
  381. // update number of trailing zeroes
  382. if (data == 0x00)
  383. zero_cnt++;
  384. else
  385. zero_cnt = 0;
  386. }
  387. return gbu->est_nal_byte_cnt + est_nal_byte;
  388. }
  389. static void put_bits(spp_enc_context context, Uint32 var, int n)
  390. {
  391. Uint32 mask;
  392. Uint32 data;
  393. gbu_t* gbu = (gbu_t *)context;
  394. if (n == 0)
  395. return;
  396. // update total rbsp count
  397. gbu->tcnt += n;
  398. if (n > gbu->bptr)
  399. {
  400. // write data
  401. mask = (1 << gbu->bptr) - 1;
  402. data = (var >> (n - gbu->bptr)) & mask;
  403. gbu->wbuf[0] |= data;
  404. gbu->rbsp_bit_cnt += gbu->bptr;
  405. // update input data
  406. n -= gbu->bptr;
  407. // update gbu bptr
  408. gbu->bptr = 0;
  409. // write rbsp data to nbuf
  410. enc_flush_rbsp(context);
  411. }
  412. mask = (1 << n) - 1;
  413. data = var & mask;
  414. // write data
  415. gbu->wbuf[0] |= data << (gbu->bptr - n);
  416. gbu->rbsp_bit_cnt += n;
  417. // update bptr
  418. gbu->bptr -= n;
  419. if (gbu->bptr == 0)
  420. enc_flush_rbsp(context);
  421. }
  422. static void put_ue(spp_enc_context context, Uint32 var)
  423. {
  424. Int32 num;
  425. Uint32 data;
  426. num = -1;
  427. data = var + 1;
  428. while (data)
  429. {
  430. data = data >> 1;
  431. num++;
  432. }
  433. // leading zero bits
  434. put_bits(context, 0, num);
  435. put_bits(context, var+1, num+1);
  436. }