transport_packet.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * section and descriptor parser
  3. *
  4. * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "transport_packet.h"
  21. #define CONTINUITY_VALID 0x80
  22. #define CONTINUITY_DUPESEEN 0x40
  23. int transport_packet_values_extract(struct transport_packet *pkt,
  24. struct transport_values *out,
  25. enum transport_value extract)
  26. {
  27. uint8_t *end = (uint8_t*) pkt + TRANSPORT_PACKET_LENGTH;
  28. uint8_t *adapend;
  29. uint8_t *pos = (uint8_t*) pkt + sizeof(struct transport_packet);
  30. enum transport_value extracted = 0;
  31. enum transport_adaptation_flags adapflags = 0;
  32. enum transport_adaptation_extension_flags adapextflags = 0;
  33. int adaplength = 0;
  34. int adapextlength = 0;
  35. /* does the packet contain an adaptation field ? */
  36. if ((pkt->adaptation_field_control & 2) == 0)
  37. goto extract_payload;
  38. /* get the adaptation field length and skip the byte */
  39. adaplength = *pos++;
  40. /* do we actually have any adaptation data? */
  41. if (adaplength == 0)
  42. goto extract_payload;
  43. /* sanity check */
  44. adapend = pos + adaplength;
  45. if (adapend > end)
  46. return -1;
  47. /* extract the adaptation flags (we must have at least 1 byte to be here) */
  48. adapflags = *pos++;
  49. /* do we actually want anything else? */
  50. if ((extract & 0xffff) == 0)
  51. goto extract_payload;
  52. /* PCR? */
  53. if (adapflags & transport_adaptation_flag_pcr) {
  54. if ((pos+6) > adapend)
  55. return -1;
  56. if (extract & transport_value_pcr) {
  57. uint64_t base = ((uint64_t) pos[0] << 25) |
  58. ((uint64_t) pos[1] << 17) |
  59. ((uint64_t) pos[2] << 9) |
  60. ((uint64_t) pos[3] << 1) |
  61. ((uint64_t) pos[4] >> 7);
  62. uint64_t ext = (((uint64_t) pos[4] & 1) << 8) |
  63. (uint64_t) pos[5];
  64. out->pcr= base * 300ULL + ext;
  65. extracted |= transport_value_pcr;
  66. }
  67. pos += 6;
  68. }
  69. /* OPCR? */
  70. if (adapflags & transport_adaptation_flag_opcr) {
  71. if ((pos+6) > adapend)
  72. return -1;
  73. if (extract & transport_value_opcr) {
  74. uint64_t base = ((uint64_t) pos[0] << 25) |
  75. ((uint64_t) pos[1] << 17) |
  76. ((uint64_t) pos[2] << 9) |
  77. ((uint64_t) pos[3] << 1) |
  78. ((uint64_t) pos[4] >> 7);
  79. uint64_t ext = (((uint64_t) pos[4] & 1) << 8) |
  80. (uint64_t) pos[5];
  81. out->opcr= base * 300ULL + ext;
  82. extracted |= transport_value_opcr;
  83. }
  84. pos += 6;
  85. }
  86. /* splice countdown? */
  87. if (adapflags & transport_adaptation_flag_splicing_point) {
  88. if ((pos+1) > adapend)
  89. return -1;
  90. if (extract & transport_value_splice_countdown) {
  91. out->splice_countdown = *pos;
  92. extracted |= transport_value_splice_countdown;
  93. }
  94. pos++;
  95. }
  96. /* private data? */
  97. if (adapflags & transport_adaptation_flag_private_data) {
  98. if ((pos+1) > adapend)
  99. return -1;
  100. if ((pos+1+*pos) > adapend)
  101. return -1;
  102. if (extract & transport_value_private_data) {
  103. out->private_data_length = *pos;
  104. out->private_data = pos + 1;
  105. extracted |= transport_value_private_data;
  106. }
  107. pos += 1 + *pos;
  108. }
  109. /* is there an adaptation extension? */
  110. if (!(adapflags & transport_adaptation_flag_extension))
  111. goto extract_payload;
  112. /* get/check the length */
  113. if (pos >= adapend)
  114. return -1;
  115. adapextlength = *pos++;
  116. if ((pos + adapextlength) > adapend)
  117. return -1;
  118. /* do we want/have anything in the adaptation extension? */
  119. if (((extract & 0xff00) == 0) || (adapextlength == 0))
  120. goto extract_payload;
  121. /* extract the adaptation extension flags (we must have at least 1 byte
  122. * to be here) */
  123. adapextflags = *pos++;
  124. /* LTW? */
  125. if (adapextflags & transport_adaptation_extension_flag_ltw) {
  126. if ((pos+2) > adapend)
  127. return -1;
  128. if (extract & transport_value_ltw) {
  129. if (*pos & 0x80) {
  130. out->ltw_offset = ((pos[0] & 0x7f) << 8) |
  131. (pos[1]);
  132. extracted |= transport_value_ltw;
  133. }
  134. }
  135. pos += 2;
  136. }
  137. /* piecewise_rate? */
  138. if (adapextflags & transport_adaptation_extension_flag_piecewise_rate) {
  139. if ((pos+3) > adapend)
  140. return -1;
  141. if (extract & transport_value_piecewise_rate) {
  142. out->piecewise_rate = ((pos[0] & 0x3f) << 16) |
  143. (pos[1] << 8) |
  144. pos[2];
  145. extracted |= transport_value_piecewise_rate;
  146. }
  147. pos += 3;
  148. }
  149. /* seamless_splice? */
  150. if (adapextflags & transport_adaptation_extension_flag_seamless_splice) {
  151. if ((pos+5) > adapend)
  152. return -1;
  153. if (extract & transport_value_piecewise_rate) {
  154. out->splice_type = pos[0] >> 4;
  155. out->dts_next_au = ((pos[0] & 0x0e) << 29) |
  156. (pos[1] << 22) |
  157. ((pos[2] & 0xfe) << 14) |
  158. (pos[3] << 7) |
  159. ((pos[4] & 0xfe) >> 1);
  160. extracted |= transport_value_seamless_splice;
  161. }
  162. pos += 5;
  163. }
  164. extract_payload:
  165. /* does the packet contain a payload? */
  166. if (pkt->adaptation_field_control & 1) {
  167. int off = sizeof(struct transport_packet);
  168. if (pkt->adaptation_field_control & 2)
  169. off++;
  170. off += adaplength;
  171. out->payload = (uint8_t*) pkt + off;
  172. out->payload_length = TRANSPORT_PACKET_LENGTH - off;
  173. } else {
  174. out->payload = NULL;
  175. out->payload_length = 0;
  176. }
  177. out->flags = adapflags;
  178. return extracted;
  179. }
  180. int transport_packet_continuity_check(struct transport_packet *pkt,
  181. int discontinuity_indicator, unsigned char *cstate)
  182. {
  183. unsigned char pktcontinuity = pkt->continuity_counter;
  184. unsigned char prevcontinuity = *cstate & 0x0f;
  185. unsigned char nextcontinuity;
  186. /* NULL packets have undefined continuity */
  187. if (transport_packet_pid(pkt) == TRANSPORT_NULL_PID)
  188. return 0;
  189. /* is the state valid? */
  190. if (!(*cstate & CONTINUITY_VALID)) {
  191. *cstate = pktcontinuity | CONTINUITY_VALID;
  192. return 0;
  193. }
  194. /* check for discontinuity_indicator */
  195. if (discontinuity_indicator) {
  196. *cstate = pktcontinuity | CONTINUITY_VALID;
  197. return 0;
  198. }
  199. /* only packets with a payload should increment the counter */
  200. if (pkt->adaptation_field_control & 1)
  201. nextcontinuity = (prevcontinuity + 1) & 0xf;
  202. else
  203. nextcontinuity = prevcontinuity;
  204. /* check for a normal continuity progression */
  205. if (nextcontinuity == pktcontinuity) {
  206. *cstate = pktcontinuity | CONTINUITY_VALID;
  207. return 0;
  208. }
  209. /* one dupe is allowed */
  210. if ((prevcontinuity == pktcontinuity) && (!(*cstate & CONTINUITY_DUPESEEN))) {
  211. *cstate = pktcontinuity | (CONTINUITY_VALID|CONTINUITY_DUPESEEN);
  212. return 0;
  213. }
  214. /* continuity error */
  215. return -1;
  216. }