You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 line
7.6KB

  1. #include "flv-parser.h"
  2. #include "flv-header.h"
  3. #include "flv-proto.h"
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. #include <errno.h>
  8. #define N_TAG_SIZE 4 // previous tag size
  9. #define FLV_HEADER_SIZE 9 // DataOffset included
  10. #define FLV_TAG_HEADER_SIZE 11 // StreamID included
  11. #define FLV_VIDEO_CODEC_NAME(codecid) (FLV_VIDEO_H264==(codecid) ? FLV_VIDEO_AVCC : (FLV_VIDEO_H265==(codecid) ? FLV_VIDEO_HVCC : FLV_VIDEO_AV1C))
  12. static int flv_parser_audio(struct flv_audio_tag_header_t* audio, const uint8_t* data, size_t bytes, uint32_t timestamp, flv_parser_handler handler, void* param)
  13. {
  14. if (FLV_SEQUENCE_HEADER == audio->avpacket)
  15. return handler(param, FLV_AUDIO_AAC == audio->codecid ? FLV_AUDIO_ASC : FLV_AUDIO_OPUS_HEAD, data, bytes, timestamp, timestamp, 0);
  16. else
  17. return handler(param, audio->codecid, data, bytes, timestamp, timestamp, 0);
  18. }
  19. static int flv_parser_video(struct flv_video_tag_header_t* video, const uint8_t* data, size_t bytes, uint32_t timestamp, flv_parser_handler handler, void* param)
  20. {
  21. if (FLV_VIDEO_H264 == video->codecid || FLV_VIDEO_H265 == video->codecid || FLV_VIDEO_AV1 == video->codecid)
  22. {
  23. if (FLV_SEQUENCE_HEADER == video->avpacket)
  24. {
  25. return handler(param, FLV_VIDEO_CODEC_NAME(video->codecid), data, bytes, timestamp, timestamp, 0);
  26. }
  27. else if (FLV_AVPACKET == video->avpacket)
  28. {
  29. return handler(param, video->codecid, data, bytes, timestamp + video->cts, timestamp, (FLV_VIDEO_KEY_FRAME == video->keyframe) ? 1 : 0);
  30. }
  31. else if (FLV_END_OF_SEQUENCE == video->avpacket)
  32. {
  33. return 0; // AVC end of sequence (lower level NALU sequence ender is not required or supported)
  34. }
  35. else
  36. {
  37. assert(0);
  38. return -EINVAL;
  39. }
  40. }
  41. else
  42. {
  43. // Video frame data
  44. return handler(param, video->codecid, data, bytes, timestamp, timestamp, (FLV_VIDEO_KEY_FRAME == video->keyframe) ? 1 : 0);
  45. }
  46. }
  47. // http://www.cnblogs.com/musicfans/archive/2012/11/07/2819291.html
  48. // metadata keyframes/filepositions
  49. static int flv_parser_script(const uint8_t* data, size_t bytes, uint32_t timestamp, flv_parser_handler handler, void* param)
  50. {
  51. return handler(param, FLV_SCRIPT_METADATA, data, bytes, timestamp, timestamp, 0);
  52. }
  53. int flv_parser_tag(int type, const void* data, size_t bytes, uint32_t timestamp, flv_parser_handler handler, void* param)
  54. {
  55. int n;
  56. struct flv_audio_tag_header_t audio;
  57. struct flv_video_tag_header_t video;
  58. if (bytes < 1) return -EINVAL;
  59. switch (type)
  60. {
  61. case FLV_TYPE_AUDIO:
  62. n = flv_audio_tag_header_read(&audio, data, bytes);
  63. if (n < 0)
  64. return n;
  65. return flv_parser_audio(&audio, (const uint8_t*)data + n, (int)bytes - n, timestamp, handler, param);
  66. case FLV_TYPE_VIDEO:
  67. n = flv_video_tag_header_read(&video, data, bytes);
  68. if (n < 0)
  69. return n;
  70. return flv_parser_video(&video, (const uint8_t*)data + n, (int)bytes - n, timestamp, handler, param);
  71. case FLV_TYPE_SCRIPT:
  72. n = flv_data_tag_header_read(data, bytes);
  73. if (n < 0)
  74. return n;
  75. return flv_parser_script((const uint8_t*)data + n, (int)bytes - n, timestamp, handler, param);
  76. default:
  77. assert(0);
  78. return -1;
  79. }
  80. }
  81. static size_t flv_parser_append(struct flv_parser_t* parser, const uint8_t* data, size_t bytes, size_t expect)
  82. {
  83. size_t n;
  84. if (parser->bytes > expect || expect > sizeof(parser->ptr))
  85. {
  86. // invalid status, consume all
  87. assert(0);
  88. parser->bytes = expect;
  89. return bytes;
  90. }
  91. n = parser->bytes + bytes >= expect ? expect - parser->bytes : bytes;
  92. if (n > 0)
  93. {
  94. memcpy(parser->ptr + parser->bytes, data, n);
  95. parser->bytes += n;
  96. }
  97. return n;
  98. }
  99. int flv_parser_input(struct flv_parser_t* parser, const uint8_t* data, size_t bytes, flv_parser_handler handler, void* param)
  100. {
  101. int r;
  102. size_t n;
  103. uint8_t codec;
  104. uint32_t size;
  105. enum {FLV_HEADER=0, FLV_HEADER_OFFSET, FLV_PREVIOUS_SIZE, FLV_TAG_HEADER, FLV_AVHEADER_CODEC, FLV_AVHEADER_EXTRA, FLV_TAG_BODY};
  106. for (n = r = 0; bytes > 0 && n >= 0 && 0 == r; data += n, bytes -= n)
  107. {
  108. switch (parser->state)
  109. {
  110. case FLV_HEADER:
  111. n = flv_parser_append(parser, data, bytes, FLV_HEADER_SIZE);
  112. if (FLV_HEADER_SIZE == parser->bytes)
  113. {
  114. flv_header_read(&parser->header, parser->ptr, parser->bytes);
  115. if (parser->header.offset < 9 || parser->header.offset > sizeof(parser->ptr))
  116. return -1;
  117. parser->header.offset -= 9;
  118. parser->state = parser->header.offset > 0 ? FLV_HEADER_OFFSET : FLV_PREVIOUS_SIZE;
  119. parser->bytes = 0;
  120. }
  121. break;
  122. case FLV_HEADER_OFFSET:
  123. n = flv_parser_append(parser, data, bytes, parser->header.offset);
  124. if (parser->header.offset == (uint32_t)parser->bytes)
  125. {
  126. parser->bytes = 0;
  127. parser->state = FLV_PREVIOUS_SIZE;
  128. }
  129. break;
  130. case FLV_PREVIOUS_SIZE:
  131. n = flv_parser_append(parser, data, bytes, N_TAG_SIZE);
  132. if (N_TAG_SIZE == parser->bytes)
  133. {
  134. flv_tag_size_read(parser->ptr, parser->bytes, &size);
  135. assert(size == 0 || size == parser->tag.size + FLV_TAG_HEADER_SIZE);
  136. parser->bytes = 0;
  137. parser->state = FLV_TAG_HEADER;
  138. }
  139. break;
  140. case FLV_TAG_HEADER:
  141. n = flv_parser_append(parser, data, bytes, FLV_TAG_HEADER_SIZE);
  142. if (FLV_TAG_HEADER_SIZE == parser->bytes)
  143. {
  144. flv_tag_header_read(&parser->tag, parser->ptr, parser->bytes);
  145. parser->bytes = 0;
  146. parser->expect = 0;
  147. parser->state = FLV_AVHEADER_CODEC;
  148. }
  149. break;
  150. case FLV_AVHEADER_CODEC:
  151. switch (parser->tag.type)
  152. {
  153. case FLV_TYPE_AUDIO:
  154. parser->expect = 1;
  155. n = flv_parser_append(parser, data, bytes, 1);
  156. codec = (parser->ptr[0] & 0xF0) /*>> 4*/;
  157. if (FLV_AUDIO_AAC == codec || FLV_AUDIO_OPUS == codec)
  158. parser->expect = 2;
  159. break;
  160. case FLV_TYPE_VIDEO:
  161. parser->expect = 1;
  162. n = flv_parser_append(parser, data, bytes, 1);
  163. codec = (parser->ptr[0] & 0x0F);
  164. if (FLV_VIDEO_H264 == codec || FLV_VIDEO_H265 == codec || FLV_VIDEO_AV1 == codec)
  165. parser->expect = 5;
  166. break;
  167. case FLV_TYPE_SCRIPT:
  168. parser->expect = 0;
  169. n = 0; // noops
  170. break;
  171. default:
  172. assert(0);
  173. return -1; // invalid flv file
  174. }
  175. parser->state = FLV_AVHEADER_EXTRA;
  176. break;
  177. case FLV_AVHEADER_EXTRA:
  178. n = flv_parser_append(parser, data, bytes, parser->expect);
  179. if (parser->expect == parser->bytes)
  180. {
  181. if(FLV_TYPE_AUDIO == parser->tag.type)
  182. flv_audio_tag_header_read(&parser->audio, parser->ptr, parser->bytes);
  183. else if(FLV_TYPE_VIDEO == parser->tag.type)
  184. flv_video_tag_header_read(&parser->video, parser->ptr, parser->bytes);
  185. parser->bytes = 0;
  186. parser->state = FLV_TAG_BODY;
  187. parser->expect = parser->tag.size - parser->expect;
  188. parser->body = parser->alloc ? parser->alloc(param, parser->expect) : malloc(parser->expect);
  189. if (!parser->body)
  190. return -1;
  191. }
  192. break;
  193. case FLV_TAG_BODY:
  194. assert(parser->body && parser->bytes <= parser->expect);
  195. n = parser->bytes + bytes >= parser->expect ? parser->expect - parser->bytes : bytes;
  196. if(n > 0) {
  197. memmove(parser->body + parser->bytes, data, n);
  198. parser->bytes += n;
  199. }
  200. if (parser->expect == parser->bytes)
  201. {
  202. parser->bytes = 0;
  203. parser->state = FLV_PREVIOUS_SIZE;
  204. switch (parser->tag.type)
  205. {
  206. case FLV_TYPE_AUDIO:
  207. r = flv_parser_audio(&parser->audio, parser->body, parser->expect, parser->tag.timestamp, handler, param);
  208. break;
  209. case FLV_TYPE_VIDEO:
  210. r = flv_parser_video(&parser->video, parser->body, parser->expect, parser->tag.timestamp, handler, param);
  211. break;
  212. case FLV_TYPE_SCRIPT:
  213. r = flv_parser_script(parser->body, parser->expect, parser->tag.timestamp, handler, param);
  214. break;
  215. default:
  216. assert(0);
  217. r = -1;
  218. break;
  219. }
  220. parser->free ? parser->free(param, parser->body) : free(parser->body);
  221. }
  222. break;
  223. default:
  224. assert(0);
  225. return -1;
  226. }
  227. }
  228. return r;
  229. }