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.

237 line
6.1KB

  1. #include "flv-header.h"
  2. #include "flv-proto.h"
  3. #include <assert.h>
  4. #include <errno.h>
  5. #define N_TAG_SIZE 4 // previous tag size
  6. #define FLV_HEADER_SIZE 9 // DataOffset included
  7. #define FLV_TAG_HEADER_SIZE 11 // StreamID included
  8. static inline uint32_t be_read_uint32(const uint8_t* ptr)
  9. {
  10. return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
  11. }
  12. static inline void be_write_uint32(uint8_t* ptr, uint32_t val)
  13. {
  14. ptr[0] = (uint8_t)((val >> 24) & 0xFF);
  15. ptr[1] = (uint8_t)((val >> 16) & 0xFF);
  16. ptr[2] = (uint8_t)((val >> 8) & 0xFF);
  17. ptr[3] = (uint8_t)(val & 0xFF);
  18. }
  19. int flv_header_read(struct flv_header_t* flv, const uint8_t* buf, size_t len)
  20. {
  21. if (len < FLV_HEADER_SIZE || 'F' != buf[0] || 'L' != buf[1] || 'V' != buf[2])
  22. {
  23. assert(0);
  24. return -1;
  25. }
  26. flv->FLV[0] = buf[0];
  27. flv->FLV[1] = buf[1];
  28. flv->FLV[2] = buf[2];
  29. flv->version = buf[3];
  30. assert(0x00 == (buf[4] & 0xF8) && 0x00 == (buf[4] & 0x20));
  31. flv->audio = (buf[4] >> 2) & 0x01;
  32. flv->video = buf[4] & 0x01;
  33. flv->offset = be_read_uint32(buf + 5);
  34. return FLV_HEADER_SIZE;
  35. }
  36. int flv_tag_header_read(struct flv_tag_header_t* tag, const uint8_t* buf, size_t len)
  37. {
  38. if (len < FLV_TAG_HEADER_SIZE)
  39. {
  40. assert(0);
  41. return -1;
  42. }
  43. // TagType
  44. tag->type = buf[0] & 0x1F;
  45. tag->filter = (buf[0] >> 5) & 0x01;
  46. assert(FLV_TYPE_VIDEO == tag->type || FLV_TYPE_AUDIO == tag->type || FLV_TYPE_SCRIPT == tag->type);
  47. // DataSize
  48. tag->size = ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | buf[3];
  49. // TimestampExtended | Timestamp
  50. tag->timestamp = ((uint32_t)buf[4] << 16) | ((uint32_t)buf[5] << 8) | buf[6] | ((uint32_t)buf[7] << 24);
  51. // StreamID Always 0
  52. tag->streamId = ((uint32_t)buf[8] << 16) | ((uint32_t)buf[9] << 8) | buf[10];
  53. //assert(0 == tag->streamId);
  54. return FLV_TAG_HEADER_SIZE;
  55. }
  56. int flv_audio_tag_header_read(struct flv_audio_tag_header_t* audio, const uint8_t* buf, size_t len)
  57. {
  58. assert(len > 0);
  59. audio->codecid = (buf[0] & 0xF0) /*>> 4*/;
  60. audio->rate = (buf[0] & 0x0C) >> 2;
  61. audio->bits = (buf[0] & 0x02) >> 1;
  62. audio->channels = buf[0] & 0x01;
  63. if (FLV_AUDIO_AAC == audio->codecid || FLV_AUDIO_OPUS == audio->codecid)
  64. {
  65. if (len < 2)
  66. {
  67. assert(0);
  68. return -1;
  69. }
  70. audio->avpacket = buf[1];
  71. assert(FLV_SEQUENCE_HEADER == audio->avpacket || FLV_AVPACKET == audio->avpacket);
  72. return 2;
  73. }
  74. else
  75. {
  76. return 1;
  77. }
  78. }
  79. int flv_video_tag_header_read(struct flv_video_tag_header_t* video, const uint8_t* buf, size_t len)
  80. {
  81. assert(len > 0);
  82. video->keyframe = (buf[0] & 0xF0) >> 4;
  83. video->codecid = (buf[0] & 0x0F);
  84. if (FLV_VIDEO_H264 == video->codecid || FLV_VIDEO_H265 == video->codecid || FLV_VIDEO_AV1 == video->codecid)
  85. {
  86. if (len < 5)
  87. return -1;
  88. video->avpacket = buf[1]; // AVCPacketType
  89. video->cts = ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 8) | buf[4];
  90. //if (video->cts >= (1 << 23)) video->cts -= (1 << 24);
  91. video->cts = (video->cts + 0xFF800000) ^ 0xFF800000; // signed 24-integer
  92. assert(FLV_SEQUENCE_HEADER == video->avpacket || FLV_AVPACKET == video->avpacket || FLV_END_OF_SEQUENCE == video->avpacket);
  93. return 5;
  94. }
  95. else
  96. {
  97. return 1;
  98. }
  99. }
  100. int flv_data_tag_header_read(const uint8_t* buf, size_t len)
  101. {
  102. (void)buf;
  103. return (int)len;
  104. }
  105. int flv_header_write(int audio, int video, uint8_t* buf, size_t len)
  106. {
  107. if (len < FLV_HEADER_SIZE)
  108. {
  109. assert(0);
  110. return -1;
  111. }
  112. buf[0] = 'F'; // FLV signature
  113. buf[1] = 'L';
  114. buf[2] = 'V';
  115. buf[3] = 0x01; // File version
  116. buf[4] = ((audio ? 1 : 0) << 2) | (video ? 1 : 0); // Type flags (audio & video)
  117. be_write_uint32(buf + 5, FLV_HEADER_SIZE); // Data offset
  118. return FLV_HEADER_SIZE;
  119. }
  120. int flv_tag_header_write(const struct flv_tag_header_t* tag, uint8_t* buf, size_t len)
  121. {
  122. if (len < FLV_TAG_HEADER_SIZE)
  123. {
  124. assert(0);
  125. return -1;
  126. }
  127. // TagType
  128. assert(FLV_TYPE_VIDEO == tag->type || FLV_TYPE_AUDIO == tag->type || FLV_TYPE_SCRIPT == tag->type);
  129. buf[0] = (tag->type & 0x1F) | ((tag->filter & 0x01) << 5);
  130. // DataSize
  131. buf[1] = (tag->size >> 16) & 0xFF;
  132. buf[2] = (tag->size >> 8) & 0xFF;
  133. buf[3] = tag->size & 0xFF;
  134. // Timestamp
  135. buf[4] = (tag->timestamp >> 16) & 0xFF;
  136. buf[5] = (tag->timestamp >> 8) & 0xFF;
  137. buf[6] = (tag->timestamp >> 0) & 0xFF;
  138. buf[7] = (tag->timestamp >> 24) & 0xFF; // Timestamp Extended
  139. // StreamID(Always 0)
  140. buf[8] = (tag->streamId >> 16) & 0xFF;
  141. buf[9] = (tag->streamId >> 8) & 0xFF;
  142. buf[10] = (tag->streamId) & 0xFF;
  143. return FLV_TAG_HEADER_SIZE;
  144. }
  145. int flv_audio_tag_header_write(const struct flv_audio_tag_header_t* audio, uint8_t* buf, size_t len)
  146. {
  147. if ((int)len < 1 + ((FLV_AUDIO_AAC == audio->codecid || FLV_AUDIO_OPUS == audio->codecid)? 1 : 0))
  148. return -1;
  149. if (FLV_AUDIO_AAC == audio->codecid || FLV_AUDIO_OPUS == audio->codecid)
  150. {
  151. assert(FLV_SEQUENCE_HEADER == audio->avpacket || FLV_AVPACKET == audio->avpacket);
  152. buf[0] = (audio->codecid /* <<4 */) /* SoundFormat */ | (3 << 2) /* 44k-SoundRate */ | (1 << 1) /* 16-bit samples */ | 1 /* Stereo sound */;
  153. buf[1] = audio->avpacket; // AACPacketType
  154. return 2;
  155. }
  156. else
  157. {
  158. buf[0] = (audio->codecid /* <<4 */) | ((audio->rate & 0x03) << 2) | ((audio->bits & 0x01) << 1) | (audio->channels & 0x01);
  159. return 1;
  160. }
  161. }
  162. int flv_video_tag_header_write(const struct flv_video_tag_header_t* video, uint8_t* buf, size_t len)
  163. {
  164. if (len < 1)
  165. return -1;
  166. buf[0] = (video->keyframe << 4) /*FrameType*/ | (video->codecid & 0x0F) /*CodecID*/;
  167. if (FLV_VIDEO_H264 == video->codecid || FLV_VIDEO_H265 == video->codecid || FLV_VIDEO_AV1 == video->codecid)
  168. {
  169. assert(FLV_SEQUENCE_HEADER == video->avpacket || FLV_AVPACKET == video->avpacket || FLV_END_OF_SEQUENCE == video->avpacket);
  170. if (len < 5)
  171. return -1;
  172. buf[1] = video->avpacket; // AVCPacketType
  173. buf[2] = (video->cts >> 16) & 0xFF;
  174. buf[3] = (video->cts >> 8) & 0xFF;
  175. buf[4] = video->cts & 0xFF;
  176. return 5;
  177. }
  178. return 1;
  179. }
  180. int flv_data_tag_header_write(uint8_t* buf, size_t len)
  181. {
  182. (void)buf;
  183. (void)len;
  184. return 0;
  185. }
  186. int flv_tag_size_read(const uint8_t* buf, size_t len, uint32_t* size)
  187. {
  188. if(len < 4)
  189. return -1;
  190. *size = be_read_uint32(buf);
  191. return 4;
  192. }
  193. int flv_tag_size_write(uint8_t* buf, size_t len, uint32_t size)
  194. {
  195. if(len < 4)
  196. return -1;
  197. be_write_uint32(buf, size);
  198. return 4;
  199. }