LCOV - code coverage report
Current view: top level - libavformat - sccenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 53 0.0 %
Date: 2017-12-16 01:21:47 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :  * SCC muxer
       3             :  * Copyright (c) 2017 Paul B Mahol
       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             : 
      22             : #include "avformat.h"
      23             : #include "internal.h"
      24             : #include "libavutil/log.h"
      25             : #include "libavutil/intreadwrite.h"
      26             : 
      27             : typedef struct SCCContext {
      28             :     int prev_h, prev_m, prev_s, prev_f;
      29             :     int inside;
      30             :     int n;
      31             : } SCCContext;
      32             : 
      33           0 : static int scc_write_header(AVFormatContext *avf)
      34             : {
      35           0 :     SCCContext *scc = avf->priv_data;
      36             : 
      37           0 :     if (avf->nb_streams != 1 ||
      38           0 :         avf->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
      39           0 :         av_log(avf, AV_LOG_ERROR,
      40             :                "SCC supports only a single subtitles stream.\n");
      41           0 :         return AVERROR(EINVAL);
      42             :     }
      43           0 :     if (avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_EIA_608) {
      44           0 :         av_log(avf, AV_LOG_ERROR,
      45             :                "Unsupported subtitles codec: %s\n",
      46           0 :                avcodec_get_name(avf->streams[0]->codecpar->codec_id));
      47           0 :         return AVERROR(EINVAL);
      48             :     }
      49           0 :     avpriv_set_pts_info(avf->streams[0], 64, 1, 1000);
      50           0 :     avio_printf(avf->pb, "Scenarist_SCC V1.0\n");
      51             : 
      52           0 :     scc->prev_h = scc->prev_m = scc->prev_s = scc->prev_f = -1;
      53           0 :     scc->inside = 0;
      54             : 
      55           0 :     return 0;
      56             : }
      57             : 
      58           0 : static int scc_write_packet(AVFormatContext *avf, AVPacket *pkt)
      59             : {
      60           0 :     SCCContext *scc = avf->priv_data;
      61           0 :     int64_t pts = pkt->pts;
      62             :     int i, h, m, s, f;
      63             : 
      64           0 :     if (pts == AV_NOPTS_VALUE) {
      65           0 :         av_log(avf, AV_LOG_WARNING,
      66             :                "Insufficient timestamps.\n");
      67           0 :         return 0;
      68             :     }
      69             : 
      70           0 :     h = (int)(pts / (3600000));
      71           0 :     m = (int)(pts / (60000)) % 60;
      72           0 :     s = (int)(pts /  1000) % 60;
      73           0 :     f = (int)(pts %  1000) / 33;
      74             : 
      75           0 :     for (i = 0; i < pkt->size; i+=3) {
      76           0 :         if (pkt->data[i] == 0xfc && ((pkt->data[i + 1] != 0x80 || pkt->data[i + 2] != 0x80)))
      77             :             break;
      78             :     }
      79           0 :     if (i >= pkt->size)
      80           0 :         return 0;
      81             : 
      82           0 :     if (!scc->inside && (scc->prev_h != h || scc->prev_m != m || scc->prev_s != s || scc->prev_f != f)) {
      83           0 :         avio_printf(avf->pb, "\n%02d:%02d:%02d:%02d\t", h, m, s, f);
      84           0 :         scc->inside = 1;
      85             :     }
      86           0 :     for (i = 0; i < pkt->size; i+=3) {
      87           0 :         if (i + 3 > pkt->size)
      88           0 :             break;
      89             : 
      90           0 :         if (pkt->data[i] != 0xfc || (pkt->data[i + 1] == 0x80 && pkt->data[i + 2] == 0x80))
      91           0 :             continue;
      92           0 :         if (!scc->inside) {
      93           0 :             avio_printf(avf->pb, "\n%02d:%02d:%02d:%02d\t", h, m, s, f);
      94           0 :             scc->inside = 1;
      95             :         }
      96           0 :         if (scc->n > 0)
      97           0 :             avio_printf(avf->pb, " ");
      98           0 :         avio_printf(avf->pb, "%02x%02x", pkt->data[i + 1], pkt->data[i + 2]);
      99           0 :         scc->n++;
     100             :     }
     101           0 :     if (scc->inside && (scc->prev_h != h || scc->prev_m != m || scc->prev_s != s || scc->prev_f != f)) {
     102           0 :         avio_printf(avf->pb, "\n");
     103           0 :         scc->n = 0;
     104           0 :         scc->inside = 0;
     105             :     }
     106             : 
     107           0 :     scc->prev_h = h;
     108           0 :     scc->prev_m = m;
     109           0 :     scc->prev_s = s;
     110           0 :     scc->prev_f = f;
     111           0 :     return 0;
     112             : }
     113             : 
     114             : AVOutputFormat ff_scc_muxer = {
     115             :     .name           = "scc",
     116             :     .long_name      = NULL_IF_CONFIG_SMALL("Scenarist Closed Captions"),
     117             :     .extensions     = "scc",
     118             :     .priv_data_size = sizeof(SCCContext),
     119             :     .write_header   = scc_write_header,
     120             :     .write_packet   = scc_write_packet,
     121             :     .flags          = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT,
     122             :     .subtitle_codec = AV_CODEC_ID_EIA_608,
     123             : };

Generated by: LCOV version 1.13