Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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. /**
  22.  * @file
  23.  * AQTitle subtitles format demuxer
  24.  *
  25.  * @see http://web.archive.org/web/20070210095721/http://www.volny.cz/aberka/czech/aqt.html
  26.  * @see https://trac.annodex.net/wiki/AQTitle
  27.  */
  28.  
  29. #include "avformat.h"
  30. #include "internal.h"
  31. #include "subtitles.h"
  32. #include "libavutil/opt.h"
  33.  
  34. typedef struct {
  35.     const AVClass *class;
  36.     FFDemuxSubtitlesQueue q;
  37.     AVRational frame_rate;
  38. } AQTitleContext;
  39.  
  40. static int aqt_probe(AVProbeData *p)
  41. {
  42.     int frame;
  43.     const char *ptr = p->buf;
  44.  
  45.     if (sscanf(ptr, "-->> %d", &frame) == 1)
  46.         return AVPROBE_SCORE_EXTENSION;
  47.     return 0;
  48. }
  49.  
  50. static int aqt_read_header(AVFormatContext *s)
  51. {
  52.     AQTitleContext *aqt = s->priv_data;
  53.     AVStream *st = avformat_new_stream(s, NULL);
  54.     int new_event = 1;
  55.     int64_t pos = 0, frame = AV_NOPTS_VALUE;
  56.     AVPacket *sub = NULL;
  57.  
  58.     if (!st)
  59.         return AVERROR(ENOMEM);
  60.     avpriv_set_pts_info(st, 64, aqt->frame_rate.den, aqt->frame_rate.num);
  61.     st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
  62.     st->codec->codec_id   = AV_CODEC_ID_TEXT;
  63.  
  64.     while (!url_feof(s->pb)) {
  65.         char line[4096];
  66.         int len = ff_get_line(s->pb, line, sizeof(line));
  67.  
  68.         if (!len)
  69.             break;
  70.  
  71.         line[strcspn(line, "\r\n")] = 0;
  72.  
  73.         if (sscanf(line, "-->> %"SCNd64, &frame) == 1) {
  74.             new_event = 1;
  75.             pos = avio_tell(s->pb);
  76.             if (sub) {
  77.                 sub->duration = frame - sub->pts;
  78.                 sub = NULL;
  79.             }
  80.         } else if (*line) {
  81.             if (!new_event) {
  82.                 sub = ff_subtitles_queue_insert(&aqt->q, "\n", 1, 1);
  83.                 if (!sub)
  84.                     return AVERROR(ENOMEM);
  85.             }
  86.             sub = ff_subtitles_queue_insert(&aqt->q, line, strlen(line), !new_event);
  87.             if (!sub)
  88.                 return AVERROR(ENOMEM);
  89.             if (new_event) {
  90.                 sub->pts = frame;
  91.                 sub->duration = -1;
  92.                 sub->pos = pos;
  93.             }
  94.             new_event = 0;
  95.         }
  96.     }
  97.  
  98.     ff_subtitles_queue_finalize(&aqt->q);
  99.     return 0;
  100. }
  101.  
  102. static int aqt_read_packet(AVFormatContext *s, AVPacket *pkt)
  103. {
  104.     AQTitleContext *aqt = s->priv_data;
  105.     return ff_subtitles_queue_read_packet(&aqt->q, pkt);
  106. }
  107.  
  108. static int aqt_read_seek(AVFormatContext *s, int stream_index,
  109.                          int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
  110. {
  111.     AQTitleContext *aqt = s->priv_data;
  112.     return ff_subtitles_queue_seek(&aqt->q, s, stream_index,
  113.                                    min_ts, ts, max_ts, flags);
  114. }
  115.  
  116. static int aqt_read_close(AVFormatContext *s)
  117. {
  118.     AQTitleContext *aqt = s->priv_data;
  119.     ff_subtitles_queue_clean(&aqt->q);
  120.     return 0;
  121. }
  122.  
  123. #define OFFSET(x) offsetof(AQTitleContext, x)
  124. #define SD AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_DECODING_PARAM
  125. static const AVOption aqt_options[] = {
  126.     { "subfps", "set the movie frame rate", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=25}, 0, INT_MAX, SD },
  127.     { NULL }
  128. };
  129.  
  130. static const AVClass aqt_class = {
  131.     .class_name = "aqtdec",
  132.     .item_name  = av_default_item_name,
  133.     .option     = aqt_options,
  134.     .version    = LIBAVUTIL_VERSION_INT,
  135. };
  136.  
  137. AVInputFormat ff_aqtitle_demuxer = {
  138.     .name           = "aqtitle",
  139.     .long_name      = NULL_IF_CONFIG_SMALL("AQTitle subtitles"),
  140.     .priv_data_size = sizeof(AQTitleContext),
  141.     .read_probe     = aqt_probe,
  142.     .read_header    = aqt_read_header,
  143.     .read_packet    = aqt_read_packet,
  144.     .read_seek2     = aqt_read_seek,
  145.     .read_close     = aqt_read_close,
  146.     .extensions     = "aqt",
  147.     .priv_class     = &aqt_class,
  148. };
  149.