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.

368 lines
11KB

  1. /*
  2. * TED Talks captions format decoder
  3. * Copyright (c) 2012 Nicolas George
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "libavutil/bprint.h"
  22. #include "libavutil/log.h"
  23. #include "libavutil/opt.h"
  24. #include "avformat.h"
  25. #include "internal.h"
  26. #include "subtitles.h"
  27. typedef struct {
  28. AVClass *class;
  29. int64_t start_time;
  30. FFDemuxSubtitlesQueue subs;
  31. } TEDCaptionsDemuxer;
  32. static const AVOption tedcaptions_options[] = {
  33. { "start_time", "set the start time (offset) of the subtitles, in ms",
  34. offsetof(TEDCaptionsDemuxer, start_time), AV_OPT_TYPE_INT64,
  35. { .i64 = 15000 }, INT64_MIN, INT64_MAX,
  36. AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM },
  37. { NULL },
  38. };
  39. static const AVClass tedcaptions_demuxer_class = {
  40. .class_name = "tedcaptions_demuxer",
  41. .item_name = av_default_item_name,
  42. .option = tedcaptions_options,
  43. .version = LIBAVUTIL_VERSION_INT,
  44. };
  45. #define BETWEEN(a, amin, amax) ((unsigned)((a) - (amin)) <= (amax) - (amin))
  46. #define HEX_DIGIT_TEST(c) (BETWEEN(c, '0', '9') || BETWEEN((c) | 32, 'a', 'z'))
  47. #define HEX_DIGIT_VAL(c) ((c) <= '9' ? (c) - '0' : ((c) | 32) - 'a' + 10)
  48. #define ERR_CODE(c) ((c) < 0 ? (c) : AVERROR_INVALIDDATA)
  49. static void av_bprint_utf8(AVBPrint *bp, unsigned c)
  50. {
  51. int bytes, i;
  52. if (c <= 0x7F) {
  53. av_bprint_chars(bp, c, 1);
  54. return;
  55. }
  56. bytes = (av_log2(c) - 2) / 5;
  57. av_bprint_chars(bp, (c >> (bytes * 6)) | ((0xFF80 >> bytes) & 0xFF), 1);
  58. for (i = bytes - 1; i >= 0; i--)
  59. av_bprint_chars(bp, ((c >> (i * 6)) & 0x3F) | 0x80, 1);
  60. }
  61. static void next_byte(AVIOContext *pb, int *cur_byte)
  62. {
  63. uint8_t b;
  64. int ret = avio_read(pb, &b, 1);
  65. *cur_byte = ret > 0 ? b : ret == 0 ? AVERROR_EOF : ret;
  66. }
  67. static void skip_spaces(AVIOContext *pb, int *cur_byte)
  68. {
  69. while (*cur_byte == ' ' || *cur_byte == '\t' ||
  70. *cur_byte == '\n' || *cur_byte == '\r')
  71. next_byte(pb, cur_byte);
  72. }
  73. static int expect_byte(AVIOContext *pb, int *cur_byte, uint8_t c)
  74. {
  75. skip_spaces(pb, cur_byte);
  76. if (*cur_byte != c)
  77. return ERR_CODE(*cur_byte);
  78. next_byte(pb, cur_byte);
  79. return 0;
  80. }
  81. static int parse_string(AVIOContext *pb, int *cur_byte, AVBPrint *bp, int full)
  82. {
  83. int ret;
  84. ret = expect_byte(pb, cur_byte, '"');
  85. if (ret < 0)
  86. return ret;
  87. while (*cur_byte > 0 && *cur_byte != '"') {
  88. if (*cur_byte == '\\') {
  89. next_byte(pb, cur_byte);
  90. if (*cur_byte < 0)
  91. return AVERROR_INVALIDDATA;
  92. if ((*cur_byte | 32) == 'u') {
  93. unsigned chr = 0, i;
  94. for (i = 0; i < 4; i++) {
  95. next_byte(pb, cur_byte);
  96. if (!HEX_DIGIT_TEST(*cur_byte))
  97. return ERR_CODE(*cur_byte);
  98. chr = chr * 16 + HEX_DIGIT_VAL(*cur_byte);
  99. }
  100. av_bprint_utf8(bp, chr);
  101. } else {
  102. av_bprint_chars(bp, *cur_byte, 1);
  103. }
  104. } else {
  105. av_bprint_chars(bp, *cur_byte, 1);
  106. }
  107. next_byte(pb, cur_byte);
  108. }
  109. ret = expect_byte(pb, cur_byte, '"');
  110. if (ret < 0)
  111. return ret;
  112. if (full && !av_bprint_is_complete(bp))
  113. return AVERROR(ENOMEM);
  114. return 0;
  115. }
  116. static int parse_label(AVIOContext *pb, int *cur_byte, AVBPrint *bp)
  117. {
  118. int ret;
  119. av_bprint_init(bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
  120. ret = parse_string(pb, cur_byte, bp, 0);
  121. if (ret < 0)
  122. return ret;
  123. ret = expect_byte(pb, cur_byte, ':');
  124. if (ret < 0)
  125. return ret;
  126. return 0;
  127. }
  128. static int parse_boolean(AVIOContext *pb, int *cur_byte, int *result)
  129. {
  130. static const char * const text[] = { "false", "true" };
  131. const char *p;
  132. int i;
  133. skip_spaces(pb, cur_byte);
  134. for (i = 0; i < 2; i++) {
  135. p = text[i];
  136. if (*cur_byte != *p)
  137. continue;
  138. for (; *p; p++, next_byte(pb, cur_byte))
  139. if (*cur_byte != *p)
  140. return AVERROR_INVALIDDATA;
  141. if (BETWEEN(*cur_byte | 32, 'a', 'z'))
  142. return AVERROR_INVALIDDATA;
  143. *result = i;
  144. return 0;
  145. }
  146. return AVERROR_INVALIDDATA;
  147. }
  148. static int parse_int(AVIOContext *pb, int *cur_byte, int64_t *result)
  149. {
  150. int64_t val = 0;
  151. skip_spaces(pb, cur_byte);
  152. if ((unsigned)*cur_byte - '0' > 9)
  153. return AVERROR_INVALIDDATA;
  154. while (BETWEEN(*cur_byte, '0', '9')) {
  155. if (val > INT_MAX/10 - (*cur_byte - '0'))
  156. return AVERROR_INVALIDDATA;
  157. val = val * 10 + (*cur_byte - '0');
  158. next_byte(pb, cur_byte);
  159. }
  160. *result = val;
  161. return 0;
  162. }
  163. static int parse_file(AVIOContext *pb, FFDemuxSubtitlesQueue *subs)
  164. {
  165. int ret, cur_byte, start_of_par;
  166. AVBPrint label, content;
  167. int64_t pos, start, duration;
  168. AVPacket *pkt;
  169. av_bprint_init(&content, 0, AV_BPRINT_SIZE_UNLIMITED);
  170. next_byte(pb, &cur_byte);
  171. ret = expect_byte(pb, &cur_byte, '{');
  172. if (ret < 0)
  173. return AVERROR_INVALIDDATA;
  174. ret = parse_label(pb, &cur_byte, &label);
  175. if (ret < 0 || strcmp(label.str, "captions"))
  176. return AVERROR_INVALIDDATA;
  177. ret = expect_byte(pb, &cur_byte, '[');
  178. if (ret < 0)
  179. return AVERROR_INVALIDDATA;
  180. while (1) {
  181. start = duration = AV_NOPTS_VALUE;
  182. ret = expect_byte(pb, &cur_byte, '{');
  183. if (ret < 0)
  184. goto fail;
  185. pos = avio_tell(pb) - 1;
  186. while (1) {
  187. ret = parse_label(pb, &cur_byte, &label);
  188. if (ret < 0)
  189. goto fail;
  190. if (!strcmp(label.str, "startOfParagraph")) {
  191. ret = parse_boolean(pb, &cur_byte, &start_of_par);
  192. if (ret < 0)
  193. goto fail;
  194. } else if (!strcmp(label.str, "content")) {
  195. ret = parse_string(pb, &cur_byte, &content, 1);
  196. if (ret < 0)
  197. goto fail;
  198. } else if (!strcmp(label.str, "startTime")) {
  199. ret = parse_int(pb, &cur_byte, &start);
  200. if (ret < 0)
  201. goto fail;
  202. } else if (!strcmp(label.str, "duration")) {
  203. ret = parse_int(pb, &cur_byte, &duration);
  204. if (ret < 0)
  205. goto fail;
  206. } else {
  207. ret = AVERROR_INVALIDDATA;
  208. goto fail;
  209. }
  210. skip_spaces(pb, &cur_byte);
  211. if (cur_byte != ',')
  212. break;
  213. next_byte(pb, &cur_byte);
  214. }
  215. ret = expect_byte(pb, &cur_byte, '}');
  216. if (ret < 0)
  217. goto fail;
  218. if (!content.size || start == AV_NOPTS_VALUE ||
  219. duration == AV_NOPTS_VALUE) {
  220. ret = AVERROR_INVALIDDATA;
  221. goto fail;
  222. }
  223. pkt = ff_subtitles_queue_insert(subs, content.str, content.len, 0);
  224. if (!pkt) {
  225. ret = AVERROR(ENOMEM);
  226. goto fail;
  227. }
  228. pkt->pos = pos;
  229. pkt->pts = start;
  230. pkt->duration = duration;
  231. av_bprint_clear(&content);
  232. skip_spaces(pb, &cur_byte);
  233. if (cur_byte != ',')
  234. break;
  235. next_byte(pb, &cur_byte);
  236. }
  237. ret = expect_byte(pb, &cur_byte, ']');
  238. if (ret < 0)
  239. goto fail;
  240. ret = expect_byte(pb, &cur_byte, '}');
  241. if (ret < 0)
  242. goto fail;
  243. skip_spaces(pb, &cur_byte);
  244. if (cur_byte != AVERROR_EOF)
  245. ret = ERR_CODE(cur_byte);
  246. fail:
  247. av_bprint_finalize(&content, NULL);
  248. return ret;
  249. }
  250. static av_cold int tedcaptions_read_header(AVFormatContext *avf)
  251. {
  252. TEDCaptionsDemuxer *tc = avf->priv_data;
  253. AVStream *st = avformat_new_stream(avf, NULL);
  254. int ret, i;
  255. AVPacket *last;
  256. if (!st)
  257. return AVERROR(ENOMEM);
  258. ret = parse_file(avf->pb, &tc->subs);
  259. if (ret < 0) {
  260. if (ret == AVERROR_INVALIDDATA)
  261. av_log(avf, AV_LOG_ERROR, "Syntax error near offset %"PRId64".\n",
  262. avio_tell(avf->pb));
  263. ff_subtitles_queue_clean(&tc->subs);
  264. return ret;
  265. }
  266. ff_subtitles_queue_finalize(avf, &tc->subs);
  267. for (i = 0; i < tc->subs.nb_subs; i++)
  268. tc->subs.subs[i].pts += tc->start_time;
  269. last = &tc->subs.subs[tc->subs.nb_subs - 1];
  270. st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
  271. st->codecpar->codec_id = AV_CODEC_ID_TEXT;
  272. avpriv_set_pts_info(st, 64, 1, 1000);
  273. st->probe_packets = 0;
  274. st->start_time = 0;
  275. st->duration = last->pts + last->duration;
  276. st->cur_dts = 0;
  277. return 0;
  278. }
  279. static int tedcaptions_read_packet(AVFormatContext *avf, AVPacket *packet)
  280. {
  281. TEDCaptionsDemuxer *tc = avf->priv_data;
  282. return ff_subtitles_queue_read_packet(&tc->subs, packet);
  283. }
  284. static int tedcaptions_read_close(AVFormatContext *avf)
  285. {
  286. TEDCaptionsDemuxer *tc = avf->priv_data;
  287. ff_subtitles_queue_clean(&tc->subs);
  288. return 0;
  289. }
  290. static av_cold int tedcaptions_read_probe(const AVProbeData *p)
  291. {
  292. static const char *const tags[] = {
  293. "\"captions\"", "\"duration\"", "\"content\"",
  294. "\"startOfParagraph\"", "\"startTime\"",
  295. };
  296. unsigned i, count = 0;
  297. const char *t;
  298. if (p->buf[strspn(p->buf, " \t\r\n")] != '{')
  299. return 0;
  300. for (i = 0; i < FF_ARRAY_ELEMS(tags); i++) {
  301. if (!(t = strstr(p->buf, tags[i])))
  302. continue;
  303. t += strlen(tags[i]);
  304. t += strspn(t, " \t\r\n");
  305. if (*t == ':')
  306. count++;
  307. }
  308. return count == FF_ARRAY_ELEMS(tags) ? AVPROBE_SCORE_MAX :
  309. count ? AVPROBE_SCORE_EXTENSION : 0;
  310. }
  311. static int tedcaptions_read_seek(AVFormatContext *avf, int stream_index,
  312. int64_t min_ts, int64_t ts, int64_t max_ts,
  313. int flags)
  314. {
  315. TEDCaptionsDemuxer *tc = avf->priv_data;
  316. return ff_subtitles_queue_seek(&tc->subs, avf, stream_index,
  317. min_ts, ts, max_ts, flags);
  318. }
  319. AVInputFormat ff_tedcaptions_demuxer = {
  320. .name = "tedcaptions",
  321. .long_name = NULL_IF_CONFIG_SMALL("TED Talks captions"),
  322. .priv_data_size = sizeof(TEDCaptionsDemuxer),
  323. .priv_class = &tedcaptions_demuxer_class,
  324. .read_header = tedcaptions_read_header,
  325. .read_packet = tedcaptions_read_packet,
  326. .read_close = tedcaptions_read_close,
  327. .read_probe = tedcaptions_read_probe,
  328. .read_seek2 = tedcaptions_read_seek,
  329. };