LCOV - code coverage report
Current view: top level - src/libavformat - assdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 76 83 91.6 %
Date: 2017-01-28 02:43:52 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /*
       2             :  * SSA/ASS demuxer
       3             :  * Copyright (c) 2008 Michael Niedermayer
       4             :  * Copyright (c) 2014 Clément Bœsch
       5             :  *
       6             :  * This file is part of FFmpeg.
       7             :  *
       8             :  * FFmpeg is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public
      10             :  * License as published by the Free Software Foundation; either
      11             :  * version 2.1 of the License, or (at your option) any later version.
      12             :  *
      13             :  * FFmpeg is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with FFmpeg; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : #include <stdint.h>
      24             : 
      25             : #include "avformat.h"
      26             : #include "internal.h"
      27             : #include "subtitles.h"
      28             : #include "libavcodec/internal.h"
      29             : #include "libavutil/bprint.h"
      30             : 
      31             : typedef struct ASSContext {
      32             :     FFDemuxSubtitlesQueue q;
      33             :     unsigned readorder;
      34             : } ASSContext;
      35             : 
      36        5565 : static int ass_probe(AVProbeData *p)
      37             : {
      38             :     char buf[13];
      39             :     FFTextReader tr;
      40        5565 :     ff_text_init_buf(&tr, p->buf, p->buf_size);
      41             : 
      42       11137 :     while (ff_text_peek_r8(&tr) == '\r' || ff_text_peek_r8(&tr) == '\n')
      43           7 :         ff_text_r8(&tr);
      44             : 
      45        5565 :     ff_text_read(&tr, buf, sizeof(buf));
      46             : 
      47        5565 :     if (!memcmp(buf, "[Script Info]", 13))
      48           3 :         return AVPROBE_SCORE_MAX;
      49             : 
      50        5562 :     return 0;
      51             : }
      52             : 
      53           3 : static int ass_read_close(AVFormatContext *s)
      54             : {
      55           3 :     ASSContext *ass = s->priv_data;
      56           3 :     ff_subtitles_queue_clean(&ass->q);
      57           3 :     return 0;
      58             : }
      59             : 
      60         208 : static int read_dialogue(ASSContext *ass, AVBPrint *dst, const uint8_t *p,
      61             :                          int64_t *start, int *duration)
      62             : {
      63         208 :     int pos = 0;
      64             :     int64_t end;
      65             :     int hh1, mm1, ss1, ms1;
      66             :     int hh2, mm2, ss2, ms2;
      67             : 
      68         208 :     if (sscanf(p, "Dialogue: %*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d,%n",
      69             :                &hh1, &mm1, &ss1, &ms1,
      70          51 :                &hh2, &mm2, &ss2, &ms2, &pos) >= 8 && pos > 0) {
      71             : 
      72             :         /* This is not part of the sscanf itself in order to handle an actual
      73             :          * number (which would be the Layer) or the form "Marked=N" (which is
      74             :          * the old SSA field, now replaced by Layer, and will lead to Layer
      75             :          * being 0 here). */
      76          51 :         const int layer = atoi(p + 10);
      77             : 
      78          51 :         end    = (hh2*3600LL + mm2*60LL + ss2) * 100LL + ms2;
      79          51 :         *start = (hh1*3600LL + mm1*60LL + ss1) * 100LL + ms1;
      80          51 :         *duration = end - *start;
      81             : 
      82          51 :         av_bprint_clear(dst);
      83          51 :         av_bprintf(dst, "%u,%d,%s", ass->readorder++, layer, p + pos);
      84             : 
      85             :         /* right strip the buffer */
      86         357 :         while (dst->len > 0 &&
      87         255 :                dst->str[dst->len - 1] == '\r' ||
      88         102 :                dst->str[dst->len - 1] == '\n')
      89         102 :             dst->str[--dst->len] = 0;
      90          51 :         return 0;
      91             :     }
      92         157 :     return -1;
      93             : }
      94             : 
      95         211 : static int64_t get_line(AVBPrint *buf, FFTextReader *tr)
      96             : {
      97         211 :     int64_t pos = ff_text_pos(tr);
      98             : 
      99         211 :     av_bprint_clear(buf);
     100       16354 :     for (;;) {
     101       16565 :         char c = ff_text_r8(tr);
     102       16565 :         if (!c)
     103           3 :             break;
     104       16562 :         av_bprint_chars(buf, c, 1);
     105       16562 :         if (c == '\n')
     106         208 :             break;
     107             :     }
     108         211 :     return pos;
     109             : }
     110             : 
     111           3 : static int ass_read_header(AVFormatContext *s)
     112             : {
     113           3 :     ASSContext *ass = s->priv_data;
     114             :     AVBPrint header, line, rline;
     115           3 :     int res = 0;
     116             :     AVStream *st;
     117             :     FFTextReader tr;
     118           3 :     ff_text_init_avio(s, &tr, s->pb);
     119             : 
     120           3 :     st = avformat_new_stream(s, NULL);
     121           3 :     if (!st)
     122           0 :         return AVERROR(ENOMEM);
     123           3 :     avpriv_set_pts_info(st, 64, 1, 100);
     124           3 :     st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
     125           3 :     st->codecpar->codec_id   = AV_CODEC_ID_ASS;
     126             : 
     127           3 :     av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED);
     128           3 :     av_bprint_init(&line,   0, AV_BPRINT_SIZE_UNLIMITED);
     129           3 :     av_bprint_init(&rline,  0, AV_BPRINT_SIZE_UNLIMITED);
     130             : 
     131           3 :     ass->q.keep_duplicates = 1;
     132             : 
     133         208 :     for (;;) {
     134         211 :         int64_t pos = get_line(&line, &tr);
     135         211 :         int64_t ts_start = AV_NOPTS_VALUE;
     136         211 :         int duration = -1;
     137             :         AVPacket *sub;
     138             : 
     139         211 :         if (!line.str[0]) // EOF
     140           3 :             break;
     141             : 
     142         208 :         if (read_dialogue(ass, &rline, line.str, &ts_start, &duration) < 0) {
     143         157 :             av_bprintf(&header, "%s", line.str);
     144         157 :             continue;
     145             :         }
     146          51 :         sub = ff_subtitles_queue_insert(&ass->q, rline.str, rline.len, 0);
     147          51 :         if (!sub) {
     148           0 :             res = AVERROR(ENOMEM);
     149           0 :             goto end;
     150             :         }
     151          51 :         sub->pos = pos;
     152          51 :         sub->pts = ts_start;
     153          51 :         sub->duration = duration;
     154             :     }
     155             : 
     156           3 :     res = ff_bprint_to_codecpar_extradata(st->codecpar, &header);
     157           3 :     if (res < 0)
     158           0 :         goto end;
     159             : 
     160           3 :     ff_subtitles_queue_finalize(s, &ass->q);
     161             : 
     162             : end:
     163           3 :     av_bprint_finalize(&header, NULL);
     164           3 :     av_bprint_finalize(&line,   NULL);
     165           3 :     av_bprint_finalize(&rline,  NULL);
     166           3 :     return res;
     167             : }
     168             : 
     169          54 : static int ass_read_packet(AVFormatContext *s, AVPacket *pkt)
     170             : {
     171          54 :     ASSContext *ass = s->priv_data;
     172          54 :     return ff_subtitles_queue_read_packet(&ass->q, pkt);
     173             : }
     174             : 
     175           0 : static int ass_read_seek(AVFormatContext *s, int stream_index,
     176             :                          int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
     177             : {
     178           0 :     ASSContext *ass = s->priv_data;
     179           0 :     return ff_subtitles_queue_seek(&ass->q, s, stream_index,
     180             :                                    min_ts, ts, max_ts, flags);
     181             : }
     182             : 
     183             : AVInputFormat ff_ass_demuxer = {
     184             :     .name           = "ass",
     185             :     .long_name      = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
     186             :     .priv_data_size = sizeof(ASSContext),
     187             :     .read_probe     = ass_probe,
     188             :     .read_header    = ass_read_header,
     189             :     .read_packet    = ass_read_packet,
     190             :     .read_close     = ass_read_close,
     191             :     .read_seek2     = ass_read_seek,
     192             : };

Generated by: LCOV version 1.12