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.

259 line
7.1KB

  1. #include "mpeg4-avc.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. /*
  6. ISO/IEC 14496-15:2010(E) 5.2.4.1.1 Syntax (p16)
  7. aligned(8) class AVCDecoderConfigurationRecord {
  8. unsigned int(8) configurationVersion = 1;
  9. unsigned int(8) AVCProfileIndication;
  10. unsigned int(8) profile_compatibility;
  11. unsigned int(8) AVCLevelIndication;
  12. bit(6) reserved = '111111'b;
  13. unsigned int(2) lengthSizeMinusOne;
  14. bit(3) reserved = '111'b;
  15. unsigned int(5) numOfSequenceParameterSets;
  16. for (i=0; i< numOfSequenceParameterSets; i++) {
  17. unsigned int(16) sequenceParameterSetLength ;
  18. bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
  19. }
  20. unsigned int(8) numOfPictureParameterSets;
  21. for (i=0; i< numOfPictureParameterSets; i++) {
  22. unsigned int(16) pictureParameterSetLength;
  23. bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
  24. }
  25. if( profile_idc == 100 || profile_idc == 110 ||
  26. profile_idc == 122 || profile_idc == 144 )
  27. {
  28. bit(6) reserved = '111111'b;
  29. unsigned int(2) chroma_format;
  30. bit(5) reserved = '11111'b;
  31. unsigned int(3) bit_depth_luma_minus8;
  32. bit(5) reserved = '11111'b;
  33. unsigned int(3) bit_depth_chroma_minus8;
  34. unsigned int(8) numOfSequenceParameterSetExt;
  35. for (i=0; i< numOfSequenceParameterSetExt; i++) {
  36. unsigned int(16) sequenceParameterSetExtLength;
  37. bit(8*sequenceParameterSetExtLength) sequenceParameterSetExtNALUnit;
  38. }
  39. }
  40. }
  41. */
  42. int mpeg4_avc_decoder_configuration_record_load(const uint8_t* data, size_t bytes, struct mpeg4_avc_t* avc)
  43. {
  44. uint8_t i;
  45. uint32_t j;
  46. uint16_t len;
  47. uint8_t *p, *end;
  48. if (bytes < 7) return -1;
  49. assert(1 == data[0]);
  50. // avc->version = data[0];
  51. avc->profile = data[1];
  52. avc->compatibility = data[2];
  53. avc->level = data[3];
  54. avc->nalu = (data[4] & 0x03) + 1;
  55. avc->nb_sps = data[5] & 0x1F;
  56. if (avc->nb_sps > sizeof(avc->sps) / sizeof(avc->sps[0]))
  57. {
  58. assert(0);
  59. return -1; // sps <= 32
  60. }
  61. j = 6;
  62. p = avc->data;
  63. end = avc->data + sizeof(avc->data);
  64. for (i = 0; i < avc->nb_sps && j + 2 < bytes; ++i)
  65. {
  66. len = (data[j] << 8) | data[j + 1];
  67. if (j + 2 + len >= bytes || p + len > end)
  68. {
  69. assert(0);
  70. return -1;
  71. }
  72. memcpy(p, data + j + 2, len);
  73. avc->sps[i].data = p;
  74. avc->sps[i].bytes = len;
  75. j += len + 2;
  76. p += len;
  77. }
  78. if (j >= bytes || (unsigned int)data[j] > sizeof(avc->pps) / sizeof(avc->pps[0]))
  79. {
  80. assert(0);
  81. return -1;
  82. }
  83. avc->nb_pps = data[j++];
  84. for (i = 0; i < avc->nb_pps && j + 2 < bytes; i++)
  85. {
  86. len = (data[j] << 8) | data[j + 1];
  87. if (j + 2 + len > bytes || p + len > end)
  88. {
  89. assert(0);
  90. return -1;
  91. }
  92. memcpy(p, data + j + 2, len);
  93. avc->pps[i].data = p;
  94. avc->pps[i].bytes = len;
  95. j += len + 2;
  96. p += len;
  97. }
  98. avc->off = (int)(p - avc->data);
  99. return j;
  100. }
  101. int mpeg4_avc_decoder_configuration_record_save(const struct mpeg4_avc_t* avc, uint8_t* data, size_t bytes)
  102. {
  103. uint8_t i;
  104. uint8_t *p = data;
  105. assert(0 < avc->nalu && avc->nalu <= 4);
  106. if (bytes < 7 || avc->nb_sps > 32) return -1;
  107. bytes -= 7;
  108. // AVCDecoderConfigurationRecord
  109. // ISO/IEC 14496-15:2010
  110. // 5.2.4.1.1 Syntax
  111. p[0] = 1; // configurationVersion
  112. p[1] = avc->profile; // AVCProfileIndication
  113. p[2] = avc->compatibility; // profile_compatibility
  114. p[3] = avc->level; // AVCLevelIndication
  115. p[4] = 0xFC | (avc->nalu - 1); // lengthSizeMinusOne: 3
  116. p += 5;
  117. // sps
  118. *p++ = 0xE0 | avc->nb_sps;
  119. for (i = 0; i < avc->nb_sps && bytes >= (size_t)avc->sps[i].bytes + 2; i++)
  120. {
  121. *p++ = (avc->sps[i].bytes >> 8) & 0xFF;
  122. *p++ = avc->sps[i].bytes & 0xFF;
  123. memcpy(p, avc->sps[i].data, avc->sps[i].bytes);
  124. p += avc->sps[i].bytes;
  125. bytes -= avc->sps[i].bytes + 2;
  126. }
  127. if (i < avc->nb_sps) return -1; // check length
  128. // pps
  129. *p++ = avc->nb_pps;
  130. for (i = 0; i < avc->nb_pps && bytes >= (size_t)avc->pps[i].bytes + 2; i++)
  131. {
  132. *p++ = (avc->pps[i].bytes >> 8) & 0xFF;
  133. *p++ = avc->pps[i].bytes & 0xFF;
  134. memcpy(p, avc->pps[i].data, avc->pps[i].bytes);
  135. p += avc->pps[i].bytes;
  136. bytes -= avc->pps[i].bytes + 2;
  137. }
  138. if (i < avc->nb_pps) return -1; // check length
  139. if (bytes >= 4)
  140. {
  141. if (avc->profile == 100 || avc->profile == 110 ||
  142. avc->profile == 122 || avc->profile == 244 || avc->profile == 44 ||
  143. avc->profile == 83 || avc->profile == 86 || avc->profile == 118 ||
  144. avc->profile == 128 || avc->profile == 138 || avc->profile == 139 ||
  145. avc->profile == 134)
  146. {
  147. *p++ = 0xFC | avc->chroma_format_idc;
  148. *p++ = 0xF8 | avc->bit_depth_luma_minus8;
  149. *p++ = 0xF8 | avc->bit_depth_chroma_minus8;
  150. *p++ = 0; // numOfSequenceParameterSetExt
  151. }
  152. }
  153. return (int)(p - data);
  154. }
  155. #define H264_STARTCODE(p) (p[0]==0 && p[1]==0 && (p[2]==1 || (p[2]==0 && p[3]==1)))
  156. int mpeg4_avc_to_nalu(const struct mpeg4_avc_t* avc, uint8_t* data, size_t bytes)
  157. {
  158. uint8_t i;
  159. size_t k = 0;
  160. uint8_t* h264 = data;
  161. // sps
  162. for (i = 0; i < avc->nb_sps && bytes >= k + avc->sps[i].bytes + 4; i++)
  163. {
  164. if (avc->sps[i].bytes < 4 || !H264_STARTCODE(avc->sps[i].data))
  165. {
  166. h264[k++] = 0;
  167. h264[k++] = 0;
  168. h264[k++] = 0;
  169. h264[k++] = 1;
  170. }
  171. memcpy(h264 + k, avc->sps[i].data, avc->sps[i].bytes);
  172. k += avc->sps[i].bytes;
  173. }
  174. if (i < avc->nb_sps) return -1; // check length
  175. // pps
  176. for (i = 0; i < avc->nb_pps && bytes >= k + avc->pps[i].bytes + 2; i++)
  177. {
  178. if (avc->pps[i].bytes < 4 || !H264_STARTCODE(avc->pps[i].data))
  179. {
  180. h264[k++] = 0;
  181. h264[k++] = 0;
  182. h264[k++] = 0;
  183. h264[k++] = 1;
  184. }
  185. memcpy(h264 + k, avc->pps[i].data, avc->pps[i].bytes);
  186. k += avc->pps[i].bytes;
  187. }
  188. if (i < avc->nb_pps) return -1; // check length
  189. assert(k < 0x7FFF);
  190. return (int)k;
  191. }
  192. int mpeg4_avc_codecs(const struct mpeg4_avc_t* avc, char* codecs, size_t bytes)
  193. {
  194. // https://tools.ietf.org/html/rfc6381#section-3.3
  195. // https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter
  196. return snprintf(codecs, bytes, "avc1.%02x%02x%02x", avc->profile, avc->compatibility, avc->level);
  197. }
  198. #if defined(_DEBUG) || defined(DEBUG)
  199. void mpeg4_annexbtomp4_test(void);
  200. void mpeg4_avc_test(void)
  201. {
  202. const unsigned char src[] = {
  203. 0x01,0x42,0xe0,0x1e,0xff,0xe1,0x00,0x21,0x67,0x42,0xe0,0x1e,0xab,0x40,0xf0,0x28,
  204. 0xd0,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x19,0x70,0x20,0x00,0x78,0x00,0x00,0x0f,
  205. 0x00,0x16,0xb1,0xb0,0x3c,0x50,0xaa,0x80,0x80,0x01,0x00,0x04,0x28,0xce,0x3c,0x80
  206. };
  207. const unsigned char nalu[] = {
  208. 0x00,0x00,0x00,0x01,0x67,0x42,0xe0,0x1e,0xab,0x40,0xf0,0x28,0xd0,0x80,0x00,0x00,
  209. 0x00,0x80,0x00,0x00,0x19,0x70,0x20,0x00,0x78,0x00,0x00,0x0f,0x00,0x16,0xb1,0xb0,
  210. 0x3c,0x50,0xaa,0x80,0x80,0x00,0x00,0x00,0x01,0x28,0xce,0x3c,0x80
  211. };
  212. unsigned char data[sizeof(src)];
  213. struct mpeg4_avc_t avc;
  214. assert(sizeof(src) == mpeg4_avc_decoder_configuration_record_load(src, sizeof(src), &avc));
  215. assert(0x42 == avc.profile && 0xe0 == avc.compatibility && 0x1e == avc.level);
  216. assert(4 == avc.nalu && 1 == avc.nb_sps && 1 == avc.nb_pps);
  217. assert(sizeof(src) == mpeg4_avc_decoder_configuration_record_save(&avc, data, sizeof(data)));
  218. assert(0 == memcmp(src, data, sizeof(src)));
  219. mpeg4_avc_codecs(&avc, (char*)data, sizeof(data));
  220. assert(0 == memcmp("avc1.42e01e", data, 11));
  221. assert(sizeof(nalu) == mpeg4_avc_to_nalu(&avc, data, sizeof(data)));
  222. assert(0 == memcmp(nalu, data, sizeof(nalu)));
  223. mpeg4_annexbtomp4_test();
  224. }
  225. #endif