FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/sccenc.c
Date: 2024-04-26 14:42:52
Exec Total Coverage
Lines: 38 45 84.4%
Functions: 2 2 100.0%
Branches: 29 46 63.0%

Line Branch Exec Source
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 "mux.h"
25 #include "libavutil/log.h"
26 #include "libavutil/intreadwrite.h"
27
28 typedef struct SCCContext {
29 int prev_h, prev_m, prev_s, prev_f;
30 int inside;
31 int n;
32 } SCCContext;
33
34 1 static int scc_write_header(AVFormatContext *avf)
35 {
36 1 SCCContext *scc = avf->priv_data;
37
38 1 avpriv_set_pts_info(avf->streams[0], 64, 1, 1000);
39 1 avio_printf(avf->pb, "Scenarist_SCC V1.0\n");
40
41 1 scc->prev_h = scc->prev_m = scc->prev_s = scc->prev_f = -1;
42 1 scc->inside = 0;
43
44 1 return 0;
45 }
46
47 32 static int scc_write_packet(AVFormatContext *avf, AVPacket *pkt)
48 {
49 32 SCCContext *scc = avf->priv_data;
50 32 int64_t pts = pkt->pts;
51 int i, h, m, s, f;
52
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (pts == AV_NOPTS_VALUE) {
54 av_log(avf, AV_LOG_WARNING,
55 "Insufficient timestamps.\n");
56 return 0;
57 }
58
59 32 h = (int)(pts / (3600000));
60 32 m = (int)(pts / (60000)) % 60;
61 32 s = (int)(pts / 1000) % 60;
62 32 f = (int)(pts % 1000) / 33;
63
64
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 for (i = 0; i < pkt->size - 2; i+=3) {
65
2/6
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
32 if (pkt->data[i] == 0xfc && ((pkt->data[i + 1] != 0x80 || pkt->data[i + 2] != 0x80)))
66 break;
67 }
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (i >= pkt->size - 2)
69 return 0;
70
71
8/10
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 29 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
32 if (!scc->inside && (scc->prev_h != h || scc->prev_m != m || scc->prev_s != s || scc->prev_f != f)) {
72 32 avio_printf(avf->pb, "\n%02d:%02d:%02d:%02d\t", h, m, s, f);
73 32 scc->inside = 1;
74 }
75
2/2
✓ Branch 0 taken 822 times.
✓ Branch 1 taken 32 times.
854 for (i = 0; i < pkt->size; i+=3) {
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 822 times.
822 if (i + 3 > pkt->size)
77 break;
78
79
2/6
✓ Branch 0 taken 822 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 822 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
822 if (pkt->data[i] != 0xfc || (pkt->data[i + 1] == 0x80 && pkt->data[i + 2] == 0x80))
80 continue;
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 822 times.
822 if (!scc->inside) {
82 avio_printf(avf->pb, "\n%02d:%02d:%02d:%02d\t", h, m, s, f);
83 scc->inside = 1;
84 }
85
2/2
✓ Branch 0 taken 790 times.
✓ Branch 1 taken 32 times.
822 if (scc->n > 0)
86 790 avio_w8(avf->pb, ' ');
87 822 avio_printf(avf->pb, "%02x%02x", pkt->data[i + 1], pkt->data[i + 2]);
88 822 scc->n++;
89 }
90
8/10
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 29 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
32 if (scc->inside && (scc->prev_h != h || scc->prev_m != m || scc->prev_s != s || scc->prev_f != f)) {
91 32 avio_w8(avf->pb, '\n');
92 32 scc->n = 0;
93 32 scc->inside = 0;
94 }
95
96 32 scc->prev_h = h;
97 32 scc->prev_m = m;
98 32 scc->prev_s = s;
99 32 scc->prev_f = f;
100 32 return 0;
101 }
102
103 const FFOutputFormat ff_scc_muxer = {
104 .p.name = "scc",
105 .p.long_name = NULL_IF_CONFIG_SMALL("Scenarist Closed Captions"),
106 .p.extensions = "scc",
107 .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT,
108 .p.video_codec = AV_CODEC_ID_NONE,
109 .p.audio_codec = AV_CODEC_ID_NONE,
110 .p.subtitle_codec = AV_CODEC_ID_EIA_608,
111 .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
112 FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
113 .priv_data_size = sizeof(SCCContext),
114 .write_header = scc_write_header,
115 .write_packet = scc_write_packet,
116 };
117