fpvplay.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. # include <stdio.h>
  2. # include <stdint.h>
  3. # include <stdlib.h>
  4. # include <unistd.h>
  5. # include <string.h>
  6. # include <errno.h>
  7. # include <getopt.h>
  8. # include <sys/types.h>
  9. # include <sys/stat.h>
  10. # include <fcntl.h>
  11. # include <arpa/inet.h>
  12. struct fpv
  13. {
  14. uint32_t len;
  15. uint8_t type;
  16. uint32_t ms;
  17. uint8_t pad[8];
  18. } __attribute__((packed));
  19. size_t out(int fd, struct sockaddr_in *to, uint8_t *data, size_t len)
  20. {
  21. int res = 0;
  22. while (len > 0) {
  23. size_t n = len;
  24. if (n > 1400) {
  25. n = 1400;
  26. }
  27. if ((n = sendto(fd, data, n, 0, (struct sockaddr*)to, sizeof(struct sockaddr_in))) > 0) {
  28. len -= n;
  29. data += n;
  30. res += n;
  31. } else {
  32. if (errno != EAGAIN) {
  33. printf("write: %s\n", strerror(errno));
  34. } else {
  35. continue;
  36. }
  37. break;
  38. }
  39. }
  40. return res;
  41. }
  42. enum
  43. {
  44. NUT_CODED_SLICE_NON_IDR = 1, // Coded slice of a non-IDR picture
  45. NUT_CODED_SLICE_IDR = 5, // Coded slice of an IDR picture
  46. NUT_SPS = 7, // Sequence parameter set
  47. NUT_PPS = 8 // Picture parameter set
  48. };
  49. struct parameter_set
  50. {
  51. uint8_t data[256];
  52. size_t length;
  53. int found;
  54. };
  55. size_t out_v(int fd, struct sockaddr_in *to, uint8_t *data, int len)
  56. {
  57. static struct parameter_set sps = { .data = { 0, }, .length = 0, .found = 0 };
  58. static struct parameter_set pps = { .data = { 0, }, .length = 0, .found = 0 };
  59. static struct parameter_set *ps = NULL;
  60. static struct { uint8_t data[4]; int length; } marker = { .length = 0, .data = { 0, } };
  61. struct { uint8_t data[4096]; int length; } pkt = { .length = 0 };
  62. int p;
  63. for (p = 0; p < len; p++) {
  64. int c = data[p];
  65. if (marker.length == 4) {
  66. if (memcmp(marker.data, "\x00\x00\x00\x01", 4) == 0) {
  67. switch (c & 0x1F) {
  68. case NUT_SPS:
  69. memset(ps = &sps, 0, sizeof(sps));
  70. sps.found = 1;
  71. break;
  72. case NUT_PPS:
  73. memset(ps = &pps, 0, sizeof(pps));
  74. pps.found = 1;
  75. break;
  76. case NUT_CODED_SLICE_NON_IDR:
  77. case NUT_CODED_SLICE_IDR:
  78. if (sps.found == 0 && sps.length > 0) {
  79. int i; for (i = 0; i < sps.length; i++) {
  80. if (pkt.length < sizeof(pkt.data)) {
  81. pkt.data[pkt.length++] = sps.data[i];
  82. }
  83. }
  84. }
  85. sps.found = 0;
  86. if (pps.found == 0 && pps.length > 0) {
  87. int i; for (i = 0; i < pps.length; i++) {
  88. if (pkt.length < sizeof(pkt.data)) {
  89. pkt.data[pkt.length++] = pps.data[i];
  90. }
  91. }
  92. }
  93. pps.found = 0;
  94. default:
  95. ps = NULL;
  96. break;
  97. }
  98. marker.data[0] = 0;
  99. marker.data[1] = 0;
  100. marker.data[2] = 0;
  101. marker.data[3] = 0;
  102. marker.length = 0;
  103. } else {
  104. marker.data[0] = marker.data[1];
  105. marker.data[1] = marker.data[2];
  106. marker.data[2] = marker.data[3];
  107. marker.data[3] = c & 0xFF;
  108. }
  109. } else {
  110. marker.data[marker.length++] = c & 0xFF;;
  111. }
  112. if (ps != NULL) {
  113. if (ps->length < sizeof(ps->data)) {
  114. ps->data[ps->length++] = c & 0xFF;
  115. } else {
  116. memset(ps, 0, sizeof(*ps));
  117. ps = NULL;
  118. }
  119. }
  120. if (pkt.length < sizeof(pkt.data)) {
  121. pkt.data[pkt.length++] = c & 0xFF;
  122. }
  123. }
  124. return out(fd, to, pkt.data, pkt.length);
  125. }
  126. size_t in(int fd, uint8_t *data, size_t len)
  127. {
  128. int res = 0;
  129. while (len > 0) {
  130. size_t n = read(fd, data, len);
  131. if (n > 0) {
  132. len -= n;
  133. data += n;
  134. res += n;
  135. } else {
  136. if (n < 0) {
  137. if (errno != EAGAIN) {
  138. printf("read: %s\n", strerror(errno));
  139. } else {
  140. continue;
  141. }
  142. }
  143. break;
  144. }
  145. }
  146. return res;
  147. }
  148. static const char short_options[] = "s:e:t:";
  149. static const struct option long_options[] =
  150. {
  151. { "start", required_argument, NULL, 's' },
  152. { "end", required_argument, NULL, 'e' },
  153. { "to", required_argument, NULL, 't' },
  154. { 0, 0, NULL, 0 }
  155. };
  156. static int opt_s = -1;
  157. static int opt_e = -1;
  158. static char *opt_t = "127.255.255.255";
  159. int main(int argc, char *argv[])
  160. {
  161. struct fpv fpv;
  162. static uint8_t data[8 * 1024 * 1024];
  163. int i;
  164. for (;;) {
  165. int c;
  166. if ((c = getopt_long_only(argc, argv, short_options, long_options, &i)) == -1) {
  167. break;
  168. }
  169. switch (c) {
  170. case 's':
  171. opt_s = atoi(optarg);
  172. break;
  173. case 'e':
  174. opt_e = atoi(optarg);
  175. break;
  176. case 't':
  177. opt_t = optarg;
  178. break;
  179. case 0:
  180. break;
  181. default:
  182. return 1;
  183. }
  184. }
  185. struct sockaddr_in all;
  186. int on = 1;
  187. int udp;
  188. memset(&all, 0, sizeof(all));
  189. all.sin_family = AF_INET;
  190. all.sin_addr.s_addr = inet_addr(opt_t);
  191. all.sin_port = htons(0);
  192. udp = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  193. setsockopt(udp, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
  194. if ((argc - optind) < 1) {
  195. return 1;
  196. }
  197. for (i = 0; (optind + i) < argc; i++) {
  198. int fd = open(argv[optind + i], O_RDONLY);
  199. int ms = 0;
  200. if (fd >= 0) {
  201. while (1) {
  202. if (in(fd, (uint8_t*)&fpv, sizeof(fpv)) > 0) {
  203. int play = 1;
  204. if (opt_s > 0 && fpv.ms < opt_s) {
  205. play = 0;
  206. }
  207. if (opt_e > 0 && fpv.ms >= opt_e) {
  208. break;
  209. }
  210. if (play) {
  211. int sleep = fpv.ms - ms;
  212. if (sleep > 0) {
  213. usleep(sleep * 1000);
  214. }
  215. }
  216. ms = fpv.ms;
  217. if (in(fd, data, fpv.len) > 0) {
  218. if (!play) {
  219. continue;
  220. }
  221. switch (fpv.type) {
  222. case 0:
  223. all.sin_port = htons(5000);
  224. break;
  225. case 2:
  226. all.sin_port = htons(14550);
  227. break;
  228. case 5:
  229. all.sin_port = htons(5003);
  230. break;
  231. default:
  232. continue;
  233. }
  234. out(udp, &all, data, fpv.len);
  235. } else {
  236. break;
  237. }
  238. } else {
  239. break;
  240. }
  241. }
  242. close(fd);
  243. }
  244. }
  245. return 0;
  246. }