您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

820 行
25KB

  1. // https://tools.ietf.org/html/rfc8216
  2. // https://developer.apple.com/documentation/http_live_streaming/about_the_ext-x-version_tag
  3. //
  4. // audio/mpegurl
  5. // application/vnd.apple.mpegurl
  6. #include "hls-parser.h"
  7. #include "hls-string.h"
  8. #include <errno.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <assert.h>
  13. struct hls_parser_t
  14. {
  15. size_t media_capacity;
  16. size_t variant_capacity;
  17. size_t session_key_capacity;
  18. size_t session_data_capacity;
  19. struct hls_variant_t* variant;
  20. struct hls_master_t* master;
  21. size_t segment_capacity;
  22. struct hls_segment_t* segment;
  23. struct hls_segment_t* key_segment; // last segment has key
  24. struct hls_playlist_t* playlist;
  25. };
  26. enum
  27. {
  28. ATTR_VALUE_TYPE_UINT32,
  29. ATTR_VALUE_TYPE_UINT64,
  30. ATTR_VALUE_TYPE_FLOAT32,
  31. ATTR_VALUE_TYPE_FLOAT64,
  32. ATTR_VALUE_TYPE_STRING,
  33. ATTR_VALUE_TYPE_STRING_BOOL,
  34. };
  35. struct hls_tag_attr_t
  36. {
  37. int cls;
  38. const char* name;
  39. void* ptr;
  40. };
  41. #define HLS_TAG_ATTR_VALUE(a, cls0, name0, ptr0) {a.cls=cls0; a.name=name0; a.ptr=ptr0; }
  42. static int hls_parser_realloc(void** ptr, size_t* capacity, size_t len, size_t incr, size_t size);
  43. static int hls_attr_read(const char* value, size_t n, int cls, void* ptr)
  44. {
  45. switch (cls)
  46. {
  47. case ATTR_VALUE_TYPE_STRING_BOOL:
  48. *(int*)ptr = (3 == n && 0 == strncasecmp(value, "YES", 3)) ? 1 : 0;
  49. return 0;
  50. case ATTR_VALUE_TYPE_UINT32:
  51. *(uint32_t*)ptr = (uint32_t)strtoul(value, NULL, 10);
  52. break;
  53. case ATTR_VALUE_TYPE_UINT64:
  54. *(uint64_t*)ptr = (uint64_t)strtoull(value, NULL, 10);
  55. break;
  56. case ATTR_VALUE_TYPE_FLOAT32:
  57. *(float*)ptr = (float)strtod(value, NULL);
  58. break;
  59. case ATTR_VALUE_TYPE_FLOAT64:
  60. *(double*)ptr = strtod(value, NULL);
  61. break;
  62. case ATTR_VALUE_TYPE_STRING:
  63. *((char**)ptr) = (char*)value;
  64. ((char*)value)[n] = 0;
  65. break;
  66. default:
  67. assert(0);
  68. return -1;
  69. }
  70. return 0;
  71. }
  72. static int hls_parse_attrs(const char* data, size_t bytes, struct hls_tag_attr_t* attrs, size_t nattrs)
  73. {
  74. int r;
  75. size_t i, n, nn, nv;
  76. const char* ptr, *next;
  77. const char* name, *value;
  78. r = 0;
  79. for (ptr = data; ptr && ptr < data + bytes && 0 == r; ptr = next)
  80. {
  81. n = hls_strsplit(ptr, data + bytes, ",", "\"", &next);
  82. nn = hls_strsplit(ptr, ptr + n, "=", "", &value);
  83. name = hls_strtrim(ptr, &nn, " \t", " \t"); // trim SP/HTAB
  84. nv = ptr + n - value;
  85. value = hls_strtrim(value, &nv, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  86. for (i = 0; i < nattrs; i++)
  87. {
  88. if (nn == strlen(attrs[i].name) && 0 == strncasecmp(attrs[i].name, name, nn))
  89. {
  90. r = hls_attr_read(value, nv, attrs[i].cls, attrs[i].ptr);
  91. break;
  92. }
  93. }
  94. }
  95. return r;
  96. }
  97. static int hls_ext_inf(struct hls_parser_t* parser, const char* data, size_t bytes)
  98. {
  99. size_t n;
  100. const char* duration;
  101. struct hls_segment_t* segment;
  102. segment = parser->segment;
  103. n = hls_strsplit(data, data + bytes, ",", "\"", (const char**)&segment->title);
  104. duration = hls_strtrim(data, &n, " \t", " \t"); // trim SP/HTAB
  105. // decimal-floating-point or decimal-integer number
  106. segment->duration = strtod(duration, NULL);
  107. n = data + bytes - segment->title;
  108. segment->title = (char*)hls_strtrim(segment->title, &n, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  109. segment->title[n] = 0;
  110. return 0;
  111. }
  112. static int hls_ext_x_byterange(struct hls_parser_t* parser, const char* data, size_t bytes)
  113. {
  114. size_t n;
  115. const char* ptr, *next;
  116. struct hls_segment_t* segment;
  117. segment = parser->segment;
  118. n = hls_strsplit(data, data + bytes, "@", "", &next);
  119. ptr = hls_strtrim(data, &n, " \t", " \t"); // trim SP/HTAB
  120. segment->bytes = (int64_t)strtoull(ptr, NULL, 10); // decimal-integer
  121. n = data + bytes - next;
  122. next = hls_strtrim(next, &n, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  123. segment->offset = n > 0 ? (int64_t)strtoull(next, NULL, 10) : segment->offset;
  124. return 0;
  125. }
  126. static int hls_ext_x_discontinuity(struct hls_parser_t* parser, const char* data, size_t bytes)
  127. {
  128. parser->segment->discontinuity = 1;
  129. (void)data, (void)bytes;
  130. return 0;
  131. }
  132. static int hls_ext_x_key(struct hls_parser_t* parser, const char* data, size_t bytes)
  133. {
  134. int r;
  135. struct hls_segment_t* segment;
  136. struct hls_tag_attr_t attrs[5];
  137. char* iv;
  138. iv = "";
  139. segment = parser->segment;
  140. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_STRING, "METHOD", &segment->key.method);
  141. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_STRING, "URI", &segment->key.uri);
  142. HLS_TAG_ATTR_VALUE(attrs[2], ATTR_VALUE_TYPE_STRING, "IV", &iv);
  143. HLS_TAG_ATTR_VALUE(attrs[3], ATTR_VALUE_TYPE_STRING, "KEYFORMAT", &segment->key.keyformat);
  144. HLS_TAG_ATTR_VALUE(attrs[4], ATTR_VALUE_TYPE_STRING, "KEYFORMATVERSIONS", &segment->key.keyformatversions);
  145. r = hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  146. if (0 != r)
  147. return r;
  148. if (strlen(iv) == 34) // 0x + 32bits
  149. hls_base16_decode(segment->key.iv, iv + 2, 32);
  150. // It applies to every Media Segment and to every Media
  151. // Initialization Section declared by an EXT-X-MAP tag that appears
  152. // between it and the next EXT-X-KEY tag in the Playlist file with the
  153. // same KEYFORMAT attribute (or the end of the Playlist file).
  154. parser->key_segment = parser->segment; // save key_segment
  155. return 0;
  156. }
  157. static int hls_ext_x_map(struct hls_parser_t* parser, const char* data, size_t bytes)
  158. {
  159. int r;
  160. size_t n;
  161. struct hls_segment_t* segment;
  162. struct hls_tag_attr_t attrs[2];
  163. char* byterange;
  164. const char* ptr, *next;
  165. byterange = "";
  166. segment = parser->segment;
  167. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_STRING, "URI", &segment->map.uri);
  168. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_STRING, "BYTERANGE", &byterange);
  169. r = hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  170. if (0 != r)
  171. return r;
  172. n = strlen(byterange);
  173. if (n > 2)
  174. {
  175. n = hls_strsplit(byterange, byterange + n, "@", "", &next);
  176. ptr = hls_strtrim(byterange, &n, " \t", " \t"); // trim SP/HTAB
  177. segment->map.bytes = (int64_t)strtoull(ptr, NULL, 10); // decimal-integer
  178. n = byterange + n - next;
  179. next = hls_strtrim(next, &n, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  180. segment->map.offset = n > 0 ? (int64_t)strtoull(next, NULL, 10) : segment->map.offset;
  181. }
  182. return 0;
  183. }
  184. static int hls_ext_x_program_date_time(struct hls_parser_t* parser, const char* data, size_t bytes)
  185. {
  186. struct hls_segment_t* segment;
  187. segment = parser->segment;
  188. segment->program_date_time = (char*)hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  189. return 0;
  190. }
  191. static int hls_ext_x_daterange(struct hls_parser_t* parser, const char* data, size_t bytes)
  192. {
  193. struct hls_segment_t* segment;
  194. struct hls_tag_attr_t attrs[7];
  195. segment = parser->segment;
  196. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_STRING, "ID", &segment->daterange.id);
  197. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_STRING, "CLASS", &segment->daterange.cls);
  198. HLS_TAG_ATTR_VALUE(attrs[2], ATTR_VALUE_TYPE_STRING, "START-DATE", &segment->daterange.start_date);
  199. HLS_TAG_ATTR_VALUE(attrs[3], ATTR_VALUE_TYPE_STRING, "END-DATE", &segment->daterange.end_date);
  200. HLS_TAG_ATTR_VALUE(attrs[4], ATTR_VALUE_TYPE_FLOAT64, "DURATION", &segment->daterange.duration);
  201. HLS_TAG_ATTR_VALUE(attrs[5], ATTR_VALUE_TYPE_FLOAT64, "PLANNED-DURATION", &segment->daterange.planned_duration);
  202. HLS_TAG_ATTR_VALUE(attrs[6], ATTR_VALUE_TYPE_STRING_BOOL, "END-ON-NEXT", &segment->daterange.end_on_next);
  203. return hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  204. }
  205. static int hls_ext_x_targetduration(struct hls_parser_t* parser, const char* data, size_t bytes)
  206. {
  207. data = hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  208. parser->playlist->target_duration = (uint64_t)strtoull(data, NULL, 10); // decimal-integer
  209. return 0;
  210. }
  211. static int hls_ext_x_media_sequence(struct hls_parser_t* parser, const char* data, size_t bytes)
  212. {
  213. data = hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  214. parser->playlist->media_sequence = (uint64_t)strtoull(data, NULL, 10); // decimal-integer
  215. return 0;
  216. }
  217. static int hls_ext_x_discontinuity_sequence(struct hls_parser_t* parser, const char* data, size_t bytes)
  218. {
  219. data = hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  220. parser->playlist->discontinuity_sequence = (uint64_t)strtoull(data, NULL, 10); // decimal-integer
  221. return 0;
  222. }
  223. static int hls_ext_x_endlist(struct hls_parser_t* parser, const char* data, size_t bytes)
  224. {
  225. data = hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  226. parser->playlist->endlist = 1;
  227. return 0;
  228. }
  229. static int hls_ext_x_playlist_type(struct hls_parser_t* parser, const char* data, size_t bytes)
  230. {
  231. struct hls_playlist_t* playlist;
  232. playlist = parser->playlist;
  233. data = hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  234. if (5 == bytes && 0 == strncasecmp("EVENT", data, 5))
  235. playlist->type = HLS_PLAYLIST_TYPE_EVENT;
  236. else if (3 == bytes && 0 == strncasecmp("VOD", data, 3))
  237. playlist->type = HLS_PLAYLIST_TYPE_VOD;
  238. else
  239. playlist->type = HLS_PLAYLIST_TYPE_LIVE;
  240. return 0;
  241. }
  242. static int hls_ext_x_i_frames_only(struct hls_parser_t* parser, const char* data, size_t bytes)
  243. {
  244. data = hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  245. parser->playlist->i_frames_only = 1;
  246. return 0;
  247. }
  248. // If the media type is VIDEO or AUDIO, a missing URI attribute
  249. // indicates that the media data for this Rendition is included in the
  250. // Media Playlist of any EXT-X-STREAM-INF tag referencing this EXT-X-MEDIA tag.
  251. static int hls_ext_x_media(struct hls_parser_t* parser, const char* data, size_t bytes)
  252. {
  253. struct hls_media_t* media;
  254. struct hls_master_t* master;
  255. struct hls_tag_attr_t attrs[12];
  256. master = parser->master;
  257. if (0 != hls_parser_realloc((void**)&master->medias, &parser->media_capacity, master->media_count, 4, sizeof(struct hls_media_t)))
  258. return -ENOMEM;
  259. media = &master->medias[master->media_count++];
  260. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_STRING, "TYPE", &media->type);
  261. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_STRING, "URI", &media->uri);
  262. HLS_TAG_ATTR_VALUE(attrs[2], ATTR_VALUE_TYPE_STRING, "GROUP-ID", &media->group_id);
  263. HLS_TAG_ATTR_VALUE(attrs[3], ATTR_VALUE_TYPE_STRING, "LANGUAGE", &media->language);
  264. HLS_TAG_ATTR_VALUE(attrs[4], ATTR_VALUE_TYPE_STRING, "ASSOC-LANGUAGE", &media->assoc_language);
  265. HLS_TAG_ATTR_VALUE(attrs[5], ATTR_VALUE_TYPE_STRING, "NAME", &media->name);
  266. HLS_TAG_ATTR_VALUE(attrs[6], ATTR_VALUE_TYPE_STRING_BOOL, "DEFAULT", &media->is_default);
  267. HLS_TAG_ATTR_VALUE(attrs[7], ATTR_VALUE_TYPE_STRING_BOOL, "AUTOSELECT", &media->autoselect);
  268. HLS_TAG_ATTR_VALUE(attrs[8], ATTR_VALUE_TYPE_STRING_BOOL, "FORCED", &media->forced);
  269. HLS_TAG_ATTR_VALUE(attrs[9], ATTR_VALUE_TYPE_STRING, "INSTREAM-ID", &media->instream_id);
  270. HLS_TAG_ATTR_VALUE(attrs[10], ATTR_VALUE_TYPE_STRING, "CHARACTERISTICS", &media->characteristics);
  271. HLS_TAG_ATTR_VALUE(attrs[11], ATTR_VALUE_TYPE_STRING, "CHANNELS", &media->channels);
  272. return hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  273. }
  274. static int hls_ext_x_stream_inf(struct hls_parser_t* parser, const char* data, size_t bytes)
  275. {
  276. int r;
  277. struct hls_variant_t* variant;
  278. struct hls_tag_attr_t attrs[10];
  279. char* resolution;
  280. resolution = "";
  281. variant = parser->variant;
  282. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_UINT32, "BANDWIDTH", &variant->bandwidth);
  283. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_UINT32, "AVERAGE-BANDWIDTH", &variant->average_bandwidth);
  284. HLS_TAG_ATTR_VALUE(attrs[2], ATTR_VALUE_TYPE_STRING, "CODECS", &variant->codecs);
  285. HLS_TAG_ATTR_VALUE(attrs[3], ATTR_VALUE_TYPE_STRING, "RESOLUTION", &resolution);
  286. HLS_TAG_ATTR_VALUE(attrs[4], ATTR_VALUE_TYPE_FLOAT64, "FRAME-RATE", &variant->fps);
  287. HLS_TAG_ATTR_VALUE(attrs[5], ATTR_VALUE_TYPE_STRING, "HDCP-LEVEL", &variant->hdcp_level);
  288. HLS_TAG_ATTR_VALUE(attrs[6], ATTR_VALUE_TYPE_STRING, "AUDIO", &variant->audio);
  289. HLS_TAG_ATTR_VALUE(attrs[7], ATTR_VALUE_TYPE_STRING, "VIDEO", &variant->video);
  290. HLS_TAG_ATTR_VALUE(attrs[8], ATTR_VALUE_TYPE_STRING, "SUBTITLES", &variant->subtitle);
  291. HLS_TAG_ATTR_VALUE(attrs[9], ATTR_VALUE_TYPE_STRING, "CLOSED-CAPTIONS", &variant->closed_captions);
  292. r = hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  293. if (0 != r)
  294. return r;
  295. if (2 != sscanf(resolution, "%dx%d", &variant->width, &variant->height))
  296. return 0; // ignore
  297. return 0;
  298. }
  299. static int hls_ext_x_i_frame_stream_inf(struct hls_parser_t* parser, const char* data, size_t bytes)
  300. {
  301. int r;
  302. struct hls_variant_t* variant;
  303. struct hls_variant_t* iframestream;
  304. struct hls_tag_attr_t attrs[7];
  305. char* resolution;
  306. resolution = "";
  307. variant = parser->variant;
  308. if (!variant->i_frame_stream_inf)
  309. {
  310. variant->i_frame_stream_inf = calloc(1, sizeof(*variant->i_frame_stream_inf));
  311. if (!variant->i_frame_stream_inf)
  312. return -ENOMEM;
  313. }
  314. iframestream = variant->i_frame_stream_inf;
  315. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_STRING, "URI", &iframestream->uri);
  316. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_UINT32, "BANDWIDTH", &iframestream->bandwidth);
  317. HLS_TAG_ATTR_VALUE(attrs[2], ATTR_VALUE_TYPE_UINT32, "AVERAGE-BANDWIDTH", &iframestream->average_bandwidth);
  318. HLS_TAG_ATTR_VALUE(attrs[3], ATTR_VALUE_TYPE_STRING, "CODECS", &iframestream->codecs);
  319. HLS_TAG_ATTR_VALUE(attrs[4], ATTR_VALUE_TYPE_STRING, "RESOLUTION", &resolution);
  320. HLS_TAG_ATTR_VALUE(attrs[5], ATTR_VALUE_TYPE_STRING, "HDCP-LEVEL", &iframestream->hdcp_level);
  321. HLS_TAG_ATTR_VALUE(attrs[6], ATTR_VALUE_TYPE_STRING, "VIDEO", &iframestream->video);
  322. r = hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  323. if (0 != r)
  324. return r;
  325. if (2 != sscanf(resolution, "%dx%d", &iframestream->width, &iframestream->height))
  326. return 0; // ignore
  327. return 0;
  328. }
  329. static int hls_ext_x_session_data(struct hls_parser_t* parser, const char* data, size_t bytes)
  330. {
  331. struct hls_master_t* master;
  332. struct hls_tag_attr_t attrs[4];
  333. master = parser->master;
  334. if (0 != hls_parser_realloc((void**)&master->session_data, &parser->session_data_capacity, master->session_data_count, 2, sizeof(master->session_data[0])))
  335. return -ENOMEM;
  336. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_STRING, "DATA-ID", &master->session_data[master->session_data_count].data_id);
  337. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_STRING, "VALUE", &master->session_data[master->session_data_count].value);
  338. HLS_TAG_ATTR_VALUE(attrs[2], ATTR_VALUE_TYPE_STRING, "URI", &master->session_data[master->session_data_count].uri);
  339. HLS_TAG_ATTR_VALUE(attrs[3], ATTR_VALUE_TYPE_STRING, "LANGUAGE", &master->session_data[master->session_data_count].language);
  340. ++master->session_data_count;
  341. return hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  342. }
  343. static int hls_ext_x_session_key(struct hls_parser_t* parser, const char* data, size_t bytes)
  344. {
  345. int r;
  346. struct hls_master_t* master;
  347. struct hls_tag_attr_t attrs[5];
  348. char* iv;
  349. iv = "";
  350. master = parser->master;
  351. if (0 != hls_parser_realloc((void**)&master->session_key, &parser->session_key_capacity, master->session_key_count, 2, sizeof(master->session_key[0])))
  352. return -ENOMEM;
  353. HLS_TAG_ATTR_VALUE(attrs[0], ATTR_VALUE_TYPE_STRING, "METHOD", &master->session_key[master->session_key_count].method);
  354. HLS_TAG_ATTR_VALUE(attrs[1], ATTR_VALUE_TYPE_STRING, "URI", &master->session_key[master->session_key_count].uri);
  355. HLS_TAG_ATTR_VALUE(attrs[2], ATTR_VALUE_TYPE_STRING, "IV", &iv);
  356. HLS_TAG_ATTR_VALUE(attrs[3], ATTR_VALUE_TYPE_STRING, "KEYFORMAT", &master->session_key[master->session_key_count].keyformat);
  357. HLS_TAG_ATTR_VALUE(attrs[4], ATTR_VALUE_TYPE_STRING, "KEYFORMATVERSIONS", &master->session_key[master->session_key_count].keyformatversions);
  358. r = hls_parse_attrs(data, bytes, attrs, sizeof(attrs) / sizeof(attrs[0]));
  359. if (0 != r)
  360. return r;
  361. if (strlen(iv) == 34) // 0x + 32bits
  362. hls_base16_decode(master->session_key[master->session_key_count].iv, iv + 2, 32);
  363. ++master->session_key_count;
  364. return 0;
  365. }
  366. static int hls_ext_x_independent_segments(struct hls_parser_t* parser, const char* data, size_t bytes)
  367. {
  368. data = hls_strtrim(data, &bytes, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  369. if (parser->playlist)
  370. parser->playlist->independent_segments = 1;
  371. else
  372. parser->master->independent_segments = 1;
  373. return 0;
  374. }
  375. static int hls_ext_x_start(struct hls_parser_t* parser, const char* data, size_t bytes)
  376. {
  377. size_t n;
  378. int start_precise;
  379. double start_time_offset;
  380. const char* ptr, * next;
  381. n = hls_strsplit(data, data + bytes, ",", "", &next);
  382. ptr = hls_strtrim(data, &n, " \t", " \t"); // trim SP/HTAB
  383. start_time_offset = strtod(ptr, NULL); // signed-decimal-floating-point
  384. n = data + bytes - next;
  385. next = hls_strtrim(next, &n, " \t'\"", " \t'\""); // trim SP/HTAB/'/"
  386. start_precise = 3 == n && 0 == strncasecmp("YES", next, 3) ? 1 : 0;
  387. if (parser->playlist)
  388. {
  389. parser->playlist->start_time_offset = start_time_offset;
  390. parser->playlist->start_precise = start_precise;
  391. }
  392. else
  393. {
  394. parser->master->start_time_offset = start_time_offset;
  395. parser->master->start_precise = start_precise;
  396. }
  397. return 0;
  398. }
  399. static int hls_ext_x_version(struct hls_parser_t* parser, const char* data, size_t bytes)
  400. {
  401. int version;
  402. data = hls_strtrim(data, &bytes, " \t", " \t"); // trim SP/HTAB
  403. version = (int)strtoul(data, NULL, 10);
  404. if (parser->playlist)
  405. parser->playlist->version = version;
  406. else
  407. parser->master->version = version;
  408. return 0;
  409. }
  410. static int hls_parser_onuri(struct hls_parser_t* parser, const char* uri, size_t len)
  411. {
  412. //printf("uri: %.*s\n", (int)len, uri);
  413. uri = hls_strtrim(uri, &len, " \t", " \t"); // trim SP/HTAB
  414. if (parser->playlist)
  415. {
  416. if (!parser->segment)
  417. {
  418. assert(0);
  419. return -1;
  420. }
  421. parser->segment->uri = (char*)uri;
  422. parser->segment->uri[len] = 0;
  423. parser->segment = NULL;
  424. parser->playlist->count++;
  425. }
  426. else
  427. {
  428. if (!parser->variant)
  429. {
  430. assert(0);
  431. return -1;
  432. }
  433. parser->variant->uri = (char*)uri;
  434. parser->variant->uri[len] = 0;
  435. parser->variant = NULL;
  436. parser->master->variant_count++;
  437. }
  438. return 0;
  439. }
  440. static const struct
  441. {
  442. int cls; // 0-any, 1-playlist, 2-master
  443. const char* name;
  444. int (*parser)(struct hls_parser_t* parser, const char* attrs, size_t bytes);
  445. } s_tags[] = {
  446. // 4.3.2. Media Segment Tags
  447. { HLS_M3U8_PLAYLIST, "EXTINF", hls_ext_inf },
  448. { HLS_M3U8_PLAYLIST, "EXT-X-BYTERANGE", hls_ext_x_byterange },
  449. { HLS_M3U8_PLAYLIST, "EXT-X-DISCONTINUITY", hls_ext_x_discontinuity },
  450. { HLS_M3U8_PLAYLIST, "EXT-X-KEY", hls_ext_x_key },
  451. { HLS_M3U8_PLAYLIST, "EXT-X-MAP", hls_ext_x_map },
  452. { HLS_M3U8_PLAYLIST, "EXT-X-PROGRAM-DATE-TIME", hls_ext_x_program_date_time },
  453. { HLS_M3U8_PLAYLIST, "EXT-X-DATERANGE", hls_ext_x_daterange },
  454. // 4.3.3. Media Playlist Tags
  455. { HLS_M3U8_PLAYLIST, "EXT-X-TARGETDURATION", hls_ext_x_targetduration },
  456. { HLS_M3U8_PLAYLIST, "EXT-X-MEDIA-SEQUENCE", hls_ext_x_media_sequence },
  457. { HLS_M3U8_PLAYLIST, "EXT-X-DISCONTINUITY-SEQUENCE",hls_ext_x_discontinuity_sequence },
  458. { HLS_M3U8_PLAYLIST, "EXT-X-ENDLIST", hls_ext_x_endlist },
  459. { HLS_M3U8_PLAYLIST, "EXT-X-PLAYLIST-TYPE", hls_ext_x_playlist_type },
  460. { HLS_M3U8_PLAYLIST, "EXT-X-I-FRAMES-ONLY", hls_ext_x_i_frames_only },
  461. // 4.3.4. Master Playlist Tags
  462. { HLS_M3U8_MASTER, "EXT-X-MEDIA", hls_ext_x_media },
  463. { HLS_M3U8_MASTER, "EXT-X-STREAM-INF", hls_ext_x_stream_inf },
  464. { HLS_M3U8_MASTER, "EXT-X-I-FRAME-STREAM-INF", hls_ext_x_i_frame_stream_inf },
  465. { HLS_M3U8_MASTER, "EXT-X-SESSION-DATA", hls_ext_x_session_data },
  466. { HLS_M3U8_MASTER, "EXT-X-SESSION-KEY", hls_ext_x_session_key },
  467. // 4.3.5. Media or Master Playlist Tags
  468. { HLS_M3U8_UNKNOWN, "EXT-X-INDEPENDENT-SEGMENTS", hls_ext_x_independent_segments },
  469. { HLS_M3U8_UNKNOWN, "EXT-X-START", hls_ext_x_start },
  470. { HLS_M3U8_UNKNOWN, "EXT-X-VERSION", hls_ext_x_version},
  471. };
  472. static int hls_parser_realloc(void** ptr, size_t* capacity, size_t len, size_t incr, size_t size)
  473. {
  474. size_t n;
  475. void* ptr1;
  476. if (len >= *capacity)
  477. {
  478. n = len / 4;
  479. n = n > incr ? n : incr;
  480. ptr1 = realloc(*ptr, (len + 1 + n) * size);
  481. if (!ptr1)
  482. return -ENOMEM;
  483. memset((uint8_t*)ptr1 + len * size, 0, (1 + n) * size);
  484. *capacity = len + 1 + n;
  485. *ptr = ptr1;
  486. }
  487. return 0;
  488. }
  489. static int hls_parser_fetch_segment(struct hls_parser_t* parser)
  490. {
  491. if (parser->segment)
  492. return 0;
  493. if(0 != hls_parser_realloc((void**)&parser->playlist->segments, &parser->segment_capacity, parser->playlist->count, 8, sizeof(struct hls_segment_t)))
  494. return -ENOMEM;
  495. parser->segment = &parser->playlist->segments[parser->playlist->count];
  496. //memset(parser->segment, 0, sizeof(*parser->segment));
  497. parser->segment->bytes = -1;
  498. parser->segment->offset = -1;
  499. parser->segment->map.bytes = -1;
  500. parser->segment->map.offset = -1;
  501. // copy default key
  502. if (parser->key_segment)
  503. memcpy(&parser->segment->key, &parser->key_segment->key, sizeof(parser->segment->key));
  504. return 0;
  505. }
  506. static int hls_parser_fetch_variant(struct hls_parser_t* parser)
  507. {
  508. if (parser->variant)
  509. return 0;
  510. if (0 != hls_parser_realloc((void**)&parser->master->variants, &parser->variant_capacity, parser->master->variant_count, 4, sizeof(struct hls_variant_t)))
  511. return -ENOMEM;
  512. parser->variant = &parser->master->variants[parser->master->variant_count];
  513. //memset(parser->variant, 0, sizeof(*parser->variant));
  514. return 0;
  515. }
  516. static int hls_parser_ontag(struct hls_parser_t* parser, const char* tag, size_t len, const char* attrs, size_t bytes)
  517. {
  518. int r;
  519. size_t i;
  520. //printf("%.*s: %.*s\n", (int)len, tag, (int)bytes, attrs);
  521. r = parser->playlist ? hls_parser_fetch_segment(parser) : hls_parser_fetch_variant(parser);
  522. if (0 != r)
  523. return r;
  524. for (i = 0; i < sizeof(s_tags) / sizeof(s_tags[0]); i++)
  525. {
  526. if (len == strlen(s_tags[i].name)+1 && 0 == strncasecmp(s_tags[i].name, tag+1, len-1))
  527. {
  528. if ((HLS_M3U8_PLAYLIST == s_tags[i].cls && !parser->playlist)
  529. || (HLS_M3U8_MASTER == s_tags[i].cls && !parser->master))
  530. return -EINVAL;
  531. r = s_tags[i].parser(parser, attrs, bytes);
  532. break;
  533. }
  534. }
  535. return r;
  536. }
  537. static int hls_parser_input(struct hls_parser_t* parser, const char* m3u8, size_t len)
  538. {
  539. int r;
  540. size_t n, ntag;
  541. const char* ptr, *next;
  542. const char* attr;
  543. r = 0;
  544. for(ptr = m3u8; ptr && ptr < m3u8 + len; ptr = next)
  545. {
  546. n = hls_strsplit(ptr, m3u8 + len, "\r\n", "", &next);
  547. ptr = hls_strtrim(ptr, &n, " \t", " \t"); // trim SP/HTAB
  548. if (n < 1)
  549. continue; // blank line
  550. if ('#' == *ptr)
  551. {
  552. if (n <= 4 || strncmp("#EXT", ptr, 4))
  553. {
  554. // ignore comment
  555. //assert(0);
  556. continue;
  557. }
  558. else
  559. {
  560. // tags
  561. attr = strpbrk(ptr, ": \t\r\n");
  562. assert(attr <= ptr + n);
  563. ntag = attr ? attr - ptr : n;
  564. attr = attr ? attr + strspn(attr, ": \t") : ptr + n;
  565. r = hls_parser_ontag(parser, ptr, ntag, attr, ptr + n - attr);
  566. }
  567. }
  568. else
  569. {
  570. // uri
  571. r = hls_parser_onuri(parser, ptr, n);
  572. }
  573. }
  574. return r;
  575. }
  576. int hls_master_parse(struct hls_master_t** master, const char* m3u8, size_t len)
  577. {
  578. int r;
  579. char* ptr;
  580. struct hls_parser_t parser;
  581. memset(&parser, 0, sizeof(parser));
  582. parser.master = (struct hls_master_t*)calloc(1, sizeof(struct hls_master_t) + len + 1);
  583. if (!parser.master)
  584. return -ENOMEM;
  585. ptr = (char*)(parser.master + 1);
  586. memcpy(ptr, m3u8, len);
  587. r = hls_parser_input(&parser, ptr, len);
  588. if (0 != r)
  589. {
  590. hls_master_free(&parser.master);
  591. return r;
  592. }
  593. *master = parser.master;
  594. return 0;
  595. }
  596. int hls_playlist_parse(struct hls_playlist_t** playlist, const char* m3u8, size_t len)
  597. {
  598. int r;
  599. char* ptr;
  600. struct hls_parser_t parser;
  601. memset(&parser, 0, sizeof(parser));
  602. parser.playlist = (struct hls_playlist_t*)calloc(1, sizeof(struct hls_playlist_t) + len + 1);
  603. if (!parser.playlist)
  604. return -ENOMEM;
  605. ptr = (char*)(parser.playlist + 1);
  606. memcpy(ptr, m3u8, len);
  607. r = hls_parser_input(&parser, ptr, len);
  608. if (0 != r)
  609. {
  610. hls_playlist_free(&parser.playlist);
  611. return r;
  612. }
  613. *playlist = parser.playlist;
  614. return 0;
  615. }
  616. int hls_master_free(struct hls_master_t** master)
  617. {
  618. size_t i;
  619. struct hls_master_t* p;
  620. if (master && *master)
  621. {
  622. p = *master;
  623. if (p->medias)
  624. free(p->medias);
  625. if (p->session_data)
  626. free(p->session_data);
  627. if (p->session_key)
  628. free(p->session_key);
  629. if (p->variants)
  630. {
  631. for (i = 0; i < p->variant_count; i++)
  632. {
  633. if (p->variants[i].i_frame_stream_inf)
  634. free(p->variants[i].i_frame_stream_inf);
  635. }
  636. free(p->variants);
  637. }
  638. free(p);
  639. *master = NULL;
  640. return 0;
  641. }
  642. return -1;
  643. }
  644. int hls_playlist_free(struct hls_playlist_t** playlist)
  645. {
  646. struct hls_playlist_t* p;
  647. if (playlist && *playlist)
  648. {
  649. p = *playlist;
  650. if (p->segments)
  651. free(p->segments);
  652. free(p);
  653. *playlist = NULL;
  654. return 0;
  655. }
  656. return -1;
  657. }
  658. int hls_parser_probe(const char* m3u8, size_t len)
  659. {
  660. size_t n;
  661. const char* ptr, *next;
  662. for (ptr = m3u8; ptr && ptr < m3u8 + len; ptr = next)
  663. {
  664. n = hls_strsplit(ptr, m3u8 + len, "\r\n", "", &next);
  665. ptr = hls_strtrim(ptr, &n, " \t", " \t"); // trim SP/HTAB
  666. if (n >= 7 && 0 == strncasecmp("#EXTINF", ptr, 7))
  667. return HLS_M3U8_PLAYLIST;
  668. else if (n >= 17 && 0 == strncasecmp("#EXT-X-STREAM-INF", ptr, 17))
  669. return HLS_M3U8_MASTER;
  670. }
  671. return HLS_M3U8_UNKNOWN;
  672. }
  673. #if defined(_DEBUG) || defined(DEBUG)
  674. void hls_parser_test(const char* m3u8)
  675. {
  676. static char data[2 * 1024 * 1024];
  677. FILE* fp = fopen(m3u8, "rb");
  678. int n = (int)fread(data, 1, sizeof(data), fp);
  679. fclose(fp);
  680. int v = hls_parser_probe(data, n);
  681. if (HLS_M3U8_MASTER == v)
  682. {
  683. struct hls_master_t* master;
  684. assert(0 == hls_master_parse(&master, data, n));
  685. hls_master_free(&master);
  686. }
  687. else if (HLS_M3U8_PLAYLIST == v)
  688. {
  689. struct hls_playlist_t* playlist;
  690. assert(0 == hls_playlist_parse(&playlist, data, n));
  691. hls_playlist_free(&playlist);
  692. }
  693. else
  694. {
  695. assert(0);
  696. }
  697. }
  698. #endif