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.

149 lines
4.3KB

  1. /*
  2. * Copyright (c) 2012 Clément Bœsch
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /**
  21. * @file
  22. * AQTitle subtitles format demuxer
  23. *
  24. * @see http://web.archive.org/web/20070210095721/http://www.volny.cz/aberka/czech/aqt.html
  25. * @see https://trac.annodex.net/wiki/AQTitle
  26. */
  27. #include "avformat.h"
  28. #include "internal.h"
  29. #include "subtitles.h"
  30. #include "libavutil/opt.h"
  31. typedef struct {
  32. const AVClass *class;
  33. FFDemuxSubtitlesQueue q;
  34. AVRational frame_rate;
  35. } AQTitleContext;
  36. static int aqt_probe(AVProbeData *p)
  37. {
  38. int frame;
  39. const char *ptr = p->buf;
  40. if (sscanf(ptr, "-->> %d", &frame) == 1)
  41. return AVPROBE_SCORE_EXTENSION;
  42. return 0;
  43. }
  44. static int aqt_read_header(AVFormatContext *s)
  45. {
  46. AQTitleContext *aqt = s->priv_data;
  47. AVStream *st = avformat_new_stream(s, NULL);
  48. int new_event = 1;
  49. int64_t pos = 0, frame = AV_NOPTS_VALUE;
  50. AVPacket *sub = NULL;
  51. if (!st)
  52. return AVERROR(ENOMEM);
  53. avpriv_set_pts_info(st, 64, aqt->frame_rate.den, aqt->frame_rate.num);
  54. st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
  55. st->codec->codec_id = AV_CODEC_ID_TEXT;
  56. while (!url_feof(s->pb)) {
  57. char line[4096];
  58. int len = ff_get_line(s->pb, line, sizeof(line));
  59. if (!len)
  60. break;
  61. line[strcspn(line, "\r\n")] = 0;
  62. if (sscanf(line, "-->> %"SCNd64, &frame) == 1) {
  63. new_event = 1;
  64. pos = avio_tell(s->pb);
  65. if (sub) {
  66. sub->duration = frame - sub->pts;
  67. sub = NULL;
  68. }
  69. } else if (*line) {
  70. if (!new_event) {
  71. sub = ff_subtitles_queue_insert(&aqt->q, "\n", 1, 1);
  72. if (!sub)
  73. return AVERROR(ENOMEM);
  74. }
  75. sub = ff_subtitles_queue_insert(&aqt->q, line, strlen(line), !new_event);
  76. if (!sub)
  77. return AVERROR(ENOMEM);
  78. if (new_event) {
  79. sub->pts = frame;
  80. sub->duration = -1;
  81. sub->pos = pos;
  82. }
  83. new_event = 0;
  84. }
  85. }
  86. ff_subtitles_queue_finalize(&aqt->q);
  87. return 0;
  88. }
  89. static int aqt_read_packet(AVFormatContext *s, AVPacket *pkt)
  90. {
  91. AQTitleContext *aqt = s->priv_data;
  92. return ff_subtitles_queue_read_packet(&aqt->q, pkt);
  93. }
  94. static int aqt_read_seek(AVFormatContext *s, int stream_index,
  95. int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
  96. {
  97. AQTitleContext *aqt = s->priv_data;
  98. return ff_subtitles_queue_seek(&aqt->q, s, stream_index,
  99. min_ts, ts, max_ts, flags);
  100. }
  101. static int aqt_read_close(AVFormatContext *s)
  102. {
  103. AQTitleContext *aqt = s->priv_data;
  104. ff_subtitles_queue_clean(&aqt->q);
  105. return 0;
  106. }
  107. #define OFFSET(x) offsetof(AQTitleContext, x)
  108. #define SD AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_DECODING_PARAM
  109. static const AVOption aqt_options[] = {
  110. { "subfps", "set the movie frame rate", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=25}, 0, INT_MAX, SD },
  111. { NULL }
  112. };
  113. static const AVClass aqt_class = {
  114. .class_name = "aqtdec",
  115. .item_name = av_default_item_name,
  116. .option = aqt_options,
  117. .version = LIBAVUTIL_VERSION_INT,
  118. };
  119. AVInputFormat ff_aqtitle_demuxer = {
  120. .name = "aqtitle",
  121. .long_name = NULL_IF_CONFIG_SMALL("AQTitle subtitles"),
  122. .priv_data_size = sizeof(AQTitleContext),
  123. .read_probe = aqt_probe,
  124. .read_header = aqt_read_header,
  125. .read_packet = aqt_read_packet,
  126. .read_seek2 = aqt_read_seek,
  127. .read_close = aqt_read_close,
  128. .extensions = "aqt",
  129. .priv_class = &aqt_class,
  130. };