PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/rtph264.c

https://github.com/gigijoe/rtph264
C | 340 lines | 204 code | 56 blank | 80 comment | 45 complexity | 46728960c7e302038540bf2f4a52e784 MD5 | raw file
  1. /*
  2. * (C) Copyright 2010
  3. * Steve Chang
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  18. * MA 02111-1307 USA
  19. *
  20. */
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <arpa/inet.h>
  26. #include <netinet/in.h>
  27. #include <sys/uio.h>
  28. #include "rtpdataheader.h"
  29. #include "rtph264.h"
  30. #include "mp4mux.h"
  31. extern AVCodec aac_encoder;
  32. extern AVCodec aac_decoder;
  33. extern AVCodec h264_decoder;
  34. extern AVCodec mpeg4_encoder;
  35. extern AVCodec mpeg4_decoder;
  36. static AVCodecContext *context = NULL;
  37. extern AVCodec aac_encoder;
  38. void RtpH264_Init()
  39. {
  40. /* must be called before using avcodec lib */
  41. avcodec_init();
  42. /* register all the codecs */
  43. // avcodec_register_all();
  44. avcodec_register(&aac_encoder);
  45. avcodec_register(&aac_decoder);
  46. avcodec_register(&h264_decoder);
  47. avcodec_register(&mpeg4_encoder);
  48. avcodec_register(&mpeg4_decoder);
  49. AVCodec *codec = avcodec_find_decoder(CODEC_ID_H264);
  50. context = avcodec_alloc_context();
  51. /* open it */
  52. if(avcodec_open(context, codec) < 0) {
  53. fprintf(stderr, "could not open codec\n");
  54. exit(EXIT_FAILURE);
  55. }
  56. Mp4mux_Init();
  57. Mp4mux_Open("/tmp/scv.mp4");
  58. }
  59. void RtpH264_Deinit()
  60. {
  61. Mp4mux_Close();
  62. avcodec_close(context);
  63. av_free(context);
  64. }
  65. static int bStop = 0;
  66. void RtpH264_Stop()
  67. {
  68. bStop = 1;
  69. }
  70. void RtpH264_Run(int sfd, RtpH264_OnPicture onPicture)
  71. {
  72. #define INBUF_SIZE (1024 * 128)
  73. uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
  74. /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
  75. memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
  76. AVFrame *picture = avcodec_alloc_frame();
  77. AVPacket avpkt;
  78. av_init_packet(&avpkt);
  79. int frame_count = 0;
  80. unsigned short sequence = 0;
  81. unsigned int timestamp = 0;
  82. while(1) {
  83. //int ready = 0;
  84. fd_set rfds;
  85. FD_ZERO(&rfds);
  86. FD_SET(sfd, &rfds);
  87. struct timeval timeout; /*Timer for operation select*/
  88. timeout.tv_sec = 0;
  89. timeout.tv_usec = 10000; /*10 ms*/
  90. if(select(sfd+1, &rfds, 0, 0, &timeout) <= 0) {
  91. if(bStop)
  92. break;
  93. else
  94. continue;
  95. }
  96. if(FD_ISSET(sfd, &rfds) <= 0)
  97. continue;
  98. rtp_hdr_t rtp;
  99. unsigned char buf[64];
  100. memset(buf, 0, 64);
  101. int r = recv(sfd, buf, sizeof(rtp_hdr_t) + 8, MSG_PEEK); /* Peek data from socket, so that we could determin how to read data from socket*/
  102. if(r <= sizeof(rtp_hdr_t) || r == -1) {
  103. recv(sfd, buf, sizeof(rtp_hdr_t) + 8, 0); /*Read invalid packet*/
  104. printf("Warning !!! Invalid packet\n");
  105. continue; /*Invalid packet ???*/
  106. }
  107. int ready = 0;
  108. /* Handle H.264 RTP Header */
  109. /* +---------------+
  110. * |0|1|2|3|4|5|6|7|
  111. * +-+-+-+-+-+-+-+-+
  112. * |F|NRI| Type |
  113. * +---------------+
  114. *
  115. * F must be 0.
  116. */
  117. unsigned char nal_ref_idc, nal_unit_type;
  118. unsigned char *header = buf + sizeof(rtp_hdr_t); /* NAL Header */
  119. nal_ref_idc = (header[0] & 0x60) >> 5; /* NRI */
  120. //printf("nal_ref_idc = %d\n", nal_ref_idc);
  121. nal_unit_type = header[0] & 0x1f; /* Type */
  122. //printf("nal_unit_type = %d\n", nal_unit_type);
  123. switch (nal_unit_type) {
  124. case 0:
  125. case 30:
  126. case 31:
  127. /* undefined */
  128. break;
  129. case 25:
  130. /* STAP-B Single-time aggregation packet 5.7.1 */
  131. /* 2 byte extra header for DON */
  132. /* fallthrough */
  133. case 24:
  134. /* STAP-A Single-time aggregation packet 5.7.1 */
  135. break;
  136. case 26:
  137. /* MTAP16 Multi-time aggregation packet 5.7.2 */
  138. /* fallthrough, not implemented */
  139. case 27:
  140. /* MTAP24 Multi-time aggregation packet 5.7.2 */
  141. break;
  142. case 28:
  143. /* FU-A Fragmentation unit 5.8 */
  144. case 29: {
  145. /* FU-B Fragmentation unit 5.8 */
  146. /* +---------------+
  147. * |0|1|2|3|4|5|6|7|
  148. * +-+-+-+-+-+-+-+-+
  149. * |S|E|R| Type |
  150. * +---------------+
  151. *
  152. * R is reserved and always 0
  153. */
  154. /*Really read packet*/
  155. struct iovec data[3];
  156. data[0].iov_base = &rtp;
  157. data[0].iov_len = sizeof(rtp_hdr_t);
  158. if(nal_unit_type == 28) {
  159. /* strip off FU indicator and FU header bytes */
  160. data[1].iov_base = buf;
  161. data[1].iov_len = 2;
  162. } else if(nal_unit_type == 29) {
  163. /* strip off FU indicator and FU header and DON bytes */
  164. data[1].iov_base = buf;
  165. data[1].iov_len = 4;
  166. }
  167. /* NAL unit starts here */
  168. if((header[1] & 0x80) == 0x80) {
  169. data[2].iov_base = &inbuf[5];
  170. data[2].iov_len = INBUF_SIZE - 5;
  171. r = readv(sfd, data, 3);
  172. if(r <= (sizeof(rtp_hdr_t) + 2)) {
  173. printf("Socket read fail !!!\n");
  174. goto cleanup;
  175. }
  176. unsigned char fu_indicator = buf[0];
  177. unsigned char fu_header = buf[1];
  178. timestamp = ntohl(rtp.ts);
  179. sequence = ntohs(rtp.seq);
  180. inbuf[0] = 0x00;
  181. inbuf[1] = 0x00;
  182. inbuf[2] = 0x00;
  183. inbuf[3] = 0x01;
  184. inbuf[4] = (fu_indicator & 0xe0) | (fu_header & 0x1f);
  185. if(nal_unit_type == 28)
  186. avpkt.size = (r - sizeof(rtp_hdr_t) - 2 + 5);
  187. else if(nal_unit_type == 29)
  188. avpkt.size = (r - sizeof(rtp_hdr_t) - 4 + 5);
  189. avpkt.data = inbuf;
  190. //printf("nalu = %d\n", fu_header & 0x1f);
  191. if((fu_header & 0x1f) == 7)
  192. avpkt.flags |= PKT_FLAG_KEY;
  193. // avpkt.pts = frame_count++;
  194. //printf("avpkt.pts = %d\n", avpkt.pts);
  195. break;
  196. } else {
  197. data[2].iov_base = inbuf + avpkt.size;
  198. data[2].iov_len = INBUF_SIZE - avpkt.size;
  199. r = readv(sfd, data, 3);
  200. //unsigned char fu_indicator = buf[0];
  201. unsigned char fu_header = buf[1];
  202. if(r <= (sizeof(rtp_hdr_t) + 2) || r == -1) {
  203. printf("Socket read fail !!!\n");
  204. goto cleanup;
  205. }
  206. if(ntohl(rtp.ts) != timestamp) {
  207. printf("Miss match timestamp %d ( expect %d )\n", ntohl(rtp.ts), timestamp);
  208. }
  209. if(ntohs(rtp.seq) != ++sequence) {
  210. printf("Wrong sequence number %u ( expect %u )\n", ntohs(rtp.seq), sequence);
  211. }
  212. if(nal_unit_type == 28)
  213. avpkt.size += (r - sizeof(rtp_hdr_t) - 2);
  214. else if(nal_unit_type == 29)
  215. avpkt.size += (r - sizeof(rtp_hdr_t) - 4);
  216. //printf("frame size : %d\n", avpkt.size);
  217. }
  218. /* NAL unit ends */
  219. if((header[1] & 0x40) == 0x40) {
  220. ready = 1; /*We are done, go to decode*/
  221. break;
  222. }
  223. break;
  224. }
  225. default: {
  226. /* 1-23 NAL unit Single NAL unit packet per H.264 5.6 */
  227. /* the entire payload is the output buffer */
  228. struct iovec data[2];
  229. data[0].iov_base = &rtp;
  230. data[0].iov_len = sizeof(rtp_hdr_t);
  231. inbuf[0] = 0x00;
  232. inbuf[1] = 0x00;
  233. inbuf[2] = 0x00;
  234. inbuf[3] = 0x01;
  235. data[1].iov_base = &inbuf[4];
  236. data[1].iov_len = INBUF_SIZE - 4;
  237. r = readv(sfd, data, 2);
  238. if(r <= sizeof(rtp_hdr_t) || r == -1) {
  239. printf("Socket read fail !!!\n");
  240. goto cleanup;
  241. }
  242. avpkt.size = (r - sizeof(rtp_hdr_t) + 4);
  243. avpkt.data = inbuf;
  244. ready = 1; /*We are done, go to decode*/
  245. break;
  246. }
  247. }
  248. int got_picture;
  249. while(ready && avpkt.size > 0) {
  250. avpkt.pts = ++frame_count;
  251. //printf("frame size : %d\n", avpkt.size);
  252. //printf("avpkt.dts = %d\n", avpkt.dts);
  253. // int len = avcodec_decode_video(context, picture, &got_picture, avpkt.data, avpkt.size);
  254. int len = avcodec_decode_video2(context, picture, &got_picture, &avpkt);
  255. //printf("context->coded_frame->pts = %d\n", context->coded_frame->pts); /* 0 */
  256. //printf("picture->pts = %d\n", picture->pts);
  257. //printf("picture->pict_type = %d\n", picture->pict_type);
  258. //printf("picture->key_frame = %d\n", picture->key_frame);
  259. //printf("picture->interlaced_frame = %d\n", picture->interlaced_frame);
  260. //printf("avpkt.duration = %d\n", avpkt.duration);
  261. Mp4Mux_WriteVideo(&avpkt, timestamp);
  262. if(len < 0) {
  263. fprintf(stderr, "Error while decoding frame\n");
  264. av_init_packet(&avpkt);
  265. break;
  266. }
  267. if(got_picture) {
  268. // printf("Decode length : %d\n", len);
  269. // fflush(stdout);
  270. /* the picture is allocated by the decoder. no need to
  271. free it */
  272. if(onPicture)
  273. onPicture(picture->data[0], picture->linesize[0], context->width, context->height);
  274. av_init_packet(&avpkt);
  275. break;
  276. }
  277. avpkt.size -= len;
  278. avpkt.data += len;
  279. }
  280. }
  281. cleanup:
  282. av_free(picture);
  283. return;
  284. }