av7110_ipack.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include "dvb_filter.h"
  3. #include "av7110_ipack.h"
  4. #include <linux/string.h> /* for memcpy() */
  5. #include <linux/vmalloc.h>
  6. void av7110_ipack_reset(struct ipack *p)
  7. {
  8. p->found = 0;
  9. p->cid = 0;
  10. p->plength = 0;
  11. p->flag1 = 0;
  12. p->flag2 = 0;
  13. p->hlength = 0;
  14. p->mpeg = 0;
  15. p->check = 0;
  16. p->which = 0;
  17. p->done = 0;
  18. p->count = 0;
  19. }
  20. int av7110_ipack_init(struct ipack *p, int size,
  21. void (*func)(u8 *buf, int size, void *priv))
  22. {
  23. if (!(p->buf = vmalloc(size))) {
  24. printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
  25. return -ENOMEM;
  26. }
  27. p->size = size;
  28. p->func = func;
  29. p->repack_subids = 0;
  30. av7110_ipack_reset(p);
  31. return 0;
  32. }
  33. void av7110_ipack_free(struct ipack *p)
  34. {
  35. vfree(p->buf);
  36. }
  37. static void send_ipack(struct ipack *p)
  38. {
  39. int off;
  40. struct dvb_audio_info ai;
  41. int ac3_off = 0;
  42. int streamid = 0;
  43. int nframes = 0;
  44. int f = 0;
  45. switch (p->mpeg) {
  46. case 2:
  47. if (p->count < 10)
  48. return;
  49. p->buf[3] = p->cid;
  50. p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
  51. p->buf[5] = (u8)((p->count - 6) & 0x00ff);
  52. if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
  53. off = 9 + p->buf[8];
  54. streamid = p->buf[off];
  55. if ((streamid & 0xf8) == 0x80) {
  56. ai.off = 0;
  57. ac3_off = ((p->buf[off + 2] << 8)|
  58. p->buf[off + 3]);
  59. if (ac3_off < p->count)
  60. f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,
  61. p->count - ac3_off, &ai, 0);
  62. if (!f) {
  63. nframes = (p->count - off - 3 - ac3_off) /
  64. ai.framesize + 1;
  65. p->buf[off + 2] = (ac3_off >> 8) & 0xff;
  66. p->buf[off + 3] = (ac3_off) & 0xff;
  67. p->buf[off + 1] = nframes;
  68. ac3_off += nframes * ai.framesize - p->count;
  69. }
  70. }
  71. }
  72. p->func(p->buf, p->count, p->data);
  73. p->buf[6] = 0x80;
  74. p->buf[7] = 0x00;
  75. p->buf[8] = 0x00;
  76. p->count = 9;
  77. if (p->repack_subids && p->cid == PRIVATE_STREAM1
  78. && (streamid & 0xf8) == 0x80) {
  79. p->count += 4;
  80. p->buf[9] = streamid;
  81. p->buf[10] = (ac3_off >> 8) & 0xff;
  82. p->buf[11] = (ac3_off) & 0xff;
  83. p->buf[12] = 0;
  84. }
  85. break;
  86. case 1:
  87. if (p->count < 8)
  88. return;
  89. p->buf[3] = p->cid;
  90. p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
  91. p->buf[5] = (u8)((p->count - 6) & 0x00ff);
  92. p->func(p->buf, p->count, p->data);
  93. p->buf[6] = 0x0f;
  94. p->count = 7;
  95. break;
  96. }
  97. }
  98. void av7110_ipack_flush(struct ipack *p)
  99. {
  100. if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)
  101. return;
  102. p->plength = p->found - 6;
  103. p->found = 0;
  104. send_ipack(p);
  105. av7110_ipack_reset(p);
  106. }
  107. static void write_ipack(struct ipack *p, const u8 *data, int count)
  108. {
  109. u8 headr[3] = { 0x00, 0x00, 0x01 };
  110. if (p->count < 6) {
  111. memcpy(p->buf, headr, 3);
  112. p->count = 6;
  113. }
  114. if (p->count + count < p->size){
  115. memcpy(p->buf+p->count, data, count);
  116. p->count += count;
  117. } else {
  118. int rest = p->size - p->count;
  119. memcpy(p->buf+p->count, data, rest);
  120. p->count += rest;
  121. send_ipack(p);
  122. if (count - rest > 0)
  123. write_ipack(p, data + rest, count - rest);
  124. }
  125. }
  126. int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
  127. {
  128. int l;
  129. int c = 0;
  130. while (c < count && (p->mpeg == 0 ||
  131. (p->mpeg == 1 && p->found < 7) ||
  132. (p->mpeg == 2 && p->found < 9))
  133. && (p->found < 5 || !p->done)) {
  134. switch (p->found) {
  135. case 0:
  136. case 1:
  137. if (buf[c] == 0x00)
  138. p->found++;
  139. else
  140. p->found = 0;
  141. c++;
  142. break;
  143. case 2:
  144. if (buf[c] == 0x01)
  145. p->found++;
  146. else if (buf[c] == 0)
  147. p->found = 2;
  148. else
  149. p->found = 0;
  150. c++;
  151. break;
  152. case 3:
  153. p->cid = 0;
  154. switch (buf[c]) {
  155. case PROG_STREAM_MAP:
  156. case PRIVATE_STREAM2:
  157. case PROG_STREAM_DIR:
  158. case ECM_STREAM :
  159. case EMM_STREAM :
  160. case PADDING_STREAM :
  161. case DSM_CC_STREAM :
  162. case ISO13522_STREAM:
  163. p->done = 1;
  164. /* fall through */
  165. case PRIVATE_STREAM1:
  166. case VIDEO_STREAM_S ... VIDEO_STREAM_E:
  167. case AUDIO_STREAM_S ... AUDIO_STREAM_E:
  168. p->found++;
  169. p->cid = buf[c];
  170. c++;
  171. break;
  172. default:
  173. p->found = 0;
  174. break;
  175. }
  176. break;
  177. case 4:
  178. if (count-c > 1) {
  179. p->plen[0] = buf[c];
  180. c++;
  181. p->plen[1] = buf[c];
  182. c++;
  183. p->found += 2;
  184. p->plength = (p->plen[0] << 8) | p->plen[1];
  185. } else {
  186. p->plen[0] = buf[c];
  187. p->found++;
  188. return count;
  189. }
  190. break;
  191. case 5:
  192. p->plen[1] = buf[c];
  193. c++;
  194. p->found++;
  195. p->plength = (p->plen[0] << 8) | p->plen[1];
  196. break;
  197. case 6:
  198. if (!p->done) {
  199. p->flag1 = buf[c];
  200. c++;
  201. p->found++;
  202. if ((p->flag1 & 0xc0) == 0x80)
  203. p->mpeg = 2;
  204. else {
  205. p->hlength = 0;
  206. p->which = 0;
  207. p->mpeg = 1;
  208. p->flag2 = 0;
  209. }
  210. }
  211. break;
  212. case 7:
  213. if (!p->done && p->mpeg == 2) {
  214. p->flag2 = buf[c];
  215. c++;
  216. p->found++;
  217. }
  218. break;
  219. case 8:
  220. if (!p->done && p->mpeg == 2) {
  221. p->hlength = buf[c];
  222. c++;
  223. p->found++;
  224. }
  225. break;
  226. }
  227. }
  228. if (c == count)
  229. return count;
  230. if (!p->plength)
  231. p->plength = MMAX_PLENGTH - 6;
  232. if (p->done || ((p->mpeg == 2 && p->found >= 9) ||
  233. (p->mpeg == 1 && p->found >= 7))) {
  234. switch (p->cid) {
  235. case AUDIO_STREAM_S ... AUDIO_STREAM_E:
  236. case VIDEO_STREAM_S ... VIDEO_STREAM_E:
  237. case PRIVATE_STREAM1:
  238. if (p->mpeg == 2 && p->found == 9) {
  239. write_ipack(p, &p->flag1, 1);
  240. write_ipack(p, &p->flag2, 1);
  241. write_ipack(p, &p->hlength, 1);
  242. }
  243. if (p->mpeg == 1 && p->found == 7)
  244. write_ipack(p, &p->flag1, 1);
  245. if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
  246. p->found < 14) {
  247. while (c < count && p->found < 14) {
  248. p->pts[p->found - 9] = buf[c];
  249. write_ipack(p, buf + c, 1);
  250. c++;
  251. p->found++;
  252. }
  253. if (c == count)
  254. return count;
  255. }
  256. if (p->mpeg == 1 && p->which < 2000) {
  257. if (p->found == 7) {
  258. p->check = p->flag1;
  259. p->hlength = 1;
  260. }
  261. while (!p->which && c < count &&
  262. p->check == 0xff){
  263. p->check = buf[c];
  264. write_ipack(p, buf + c, 1);
  265. c++;
  266. p->found++;
  267. p->hlength++;
  268. }
  269. if (c == count)
  270. return count;
  271. if ((p->check & 0xc0) == 0x40 && !p->which) {
  272. p->check = buf[c];
  273. write_ipack(p, buf + c, 1);
  274. c++;
  275. p->found++;
  276. p->hlength++;
  277. p->which = 1;
  278. if (c == count)
  279. return count;
  280. p->check = buf[c];
  281. write_ipack(p, buf + c, 1);
  282. c++;
  283. p->found++;
  284. p->hlength++;
  285. p->which = 2;
  286. if (c == count)
  287. return count;
  288. }
  289. if (p->which == 1) {
  290. p->check = buf[c];
  291. write_ipack(p, buf + c, 1);
  292. c++;
  293. p->found++;
  294. p->hlength++;
  295. p->which = 2;
  296. if (c == count)
  297. return count;
  298. }
  299. if ((p->check & 0x30) && p->check != 0xff) {
  300. p->flag2 = (p->check & 0xf0) << 2;
  301. p->pts[0] = p->check;
  302. p->which = 3;
  303. }
  304. if (c == count)
  305. return count;
  306. if (p->which > 2){
  307. if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {
  308. while (c < count && p->which < 7) {
  309. p->pts[p->which - 2] = buf[c];
  310. write_ipack(p, buf + c, 1);
  311. c++;
  312. p->found++;
  313. p->which++;
  314. p->hlength++;
  315. }
  316. if (c == count)
  317. return count;
  318. } else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {
  319. while (c < count && p->which < 12) {
  320. if (p->which < 7)
  321. p->pts[p->which - 2] = buf[c];
  322. write_ipack(p, buf + c, 1);
  323. c++;
  324. p->found++;
  325. p->which++;
  326. p->hlength++;
  327. }
  328. if (c == count)
  329. return count;
  330. }
  331. p->which = 2000;
  332. }
  333. }
  334. while (c < count && p->found < p->plength + 6) {
  335. l = count - c;
  336. if (l + p->found > p->plength + 6)
  337. l = p->plength + 6 - p->found;
  338. write_ipack(p, buf + c, l);
  339. p->found += l;
  340. c += l;
  341. }
  342. break;
  343. }
  344. if (p->done) {
  345. if (p->found + count - c < p->plength + 6) {
  346. p->found += count - c;
  347. c = count;
  348. } else {
  349. c += p->plength + 6 - p->found;
  350. p->found = p->plength + 6;
  351. }
  352. }
  353. if (p->plength && p->found == p->plength + 6) {
  354. send_ipack(p);
  355. av7110_ipack_reset(p);
  356. if (c < count)
  357. av7110_ipack_instant_repack(buf + c, count - c, p);
  358. }
  359. }
  360. return count;
  361. }