FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/tta.c
Date: 2024-04-25 15:36:26
Exec Total Coverage
Lines: 72 102 70.6%
Functions: 3 4 75.0%
Branches: 31 60 51.7%

Line Branch Exec Source
1 /*
2 * TTA demuxer
3 * Copyright (c) 2006 Alex Beregszaszi
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 "libavutil/crc.h"
23 #include "libavutil/dict.h"
24 #include "libavutil/intreadwrite.h"
25
26 #include "apetag.h"
27 #include "avformat.h"
28 #include "avio_internal.h"
29 #include "demux.h"
30 #include "internal.h"
31 #include "id3v1.h"
32
33 typedef struct TTAContext {
34 int totalframes, currentframe;
35 int frame_size;
36 int last_frame_size;
37 } TTAContext;
38
39 7128 static int tta_probe(const AVProbeData *p)
40 {
41
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7123 times.
7128 if (AV_RL32(&p->buf[0]) == MKTAG('T', 'T', 'A', '1') &&
42
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
5 (AV_RL16(&p->buf[4]) == 1 || AV_RL16(&p->buf[4]) == 2) &&
43
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 AV_RL16(&p->buf[6]) > 0 &&
44
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 AV_RL16(&p->buf[8]) > 0 &&
45
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 AV_RL32(&p->buf[10]) > 0)
46 5 return AVPROBE_SCORE_EXTENSION + 30;
47 7123 return 0;
48 }
49
50 5 static int tta_read_header(AVFormatContext *s)
51 {
52 5 TTAContext *c = s->priv_data;
53 AVStream *st;
54 int i, channels, bps, samplerate;
55 int64_t framepos, start_offset;
56 uint32_t nb_samples, crc;
57
58 5 ff_id3v1_read(s);
59
60 5 start_offset = avio_tell(s->pb);
61
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (start_offset < 0)
62 return start_offset;
63 5 ffio_init_checksum(s->pb, ff_crcEDB88320_update, UINT32_MAX);
64
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (avio_rl32(s->pb) != AV_RL32("TTA1"))
65 return AVERROR_INVALIDDATA;
66
67 5 avio_skip(s->pb, 2); // FIXME: flags
68 5 channels = avio_rl16(s->pb);
69 5 bps = avio_rl16(s->pb);
70 5 samplerate = avio_rl32(s->pb);
71
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if(samplerate <= 0 || samplerate > 1000000){
72 av_log(s, AV_LOG_ERROR, "nonsense samplerate\n");
73 return AVERROR_INVALIDDATA;
74 }
75
76 5 nb_samples = avio_rl32(s->pb);
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!nb_samples) {
78 av_log(s, AV_LOG_ERROR, "invalid number of samples\n");
79 return AVERROR_INVALIDDATA;
80 }
81
82 5 crc = ffio_get_checksum(s->pb) ^ UINT32_MAX;
83
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
5 if (crc != avio_rl32(s->pb) && s->error_recognition & AV_EF_CRCCHECK) {
84 av_log(s, AV_LOG_ERROR, "Header CRC error\n");
85 return AVERROR_INVALIDDATA;
86 }
87
88 5 c->frame_size = samplerate * 256 / 245;
89 5 c->last_frame_size = nb_samples % c->frame_size;
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!c->last_frame_size)
91 c->last_frame_size = c->frame_size;
92 5 c->totalframes = nb_samples / c->frame_size + (c->last_frame_size < c->frame_size);
93 5 c->currentframe = 0;
94
95
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if(c->totalframes >= (INT_MAX - 4)/sizeof(uint32_t) || c->totalframes <= 0){
96 av_log(s, AV_LOG_ERROR, "totalframes %d invalid\n", c->totalframes);
97 return AVERROR_INVALIDDATA;
98 }
99
100 5 st = avformat_new_stream(s, NULL);
101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!st)
102 return AVERROR(ENOMEM);
103
104 5 avpriv_set_pts_info(st, 64, 1, samplerate);
105 5 st->start_time = 0;
106 5 st->duration = nb_samples;
107
108 5 framepos = avio_tell(s->pb);
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (framepos < 0)
110 return framepos;
111 5 framepos += 4 * c->totalframes + 4;
112
113
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (ff_alloc_extradata(st->codecpar, avio_tell(s->pb) - start_offset))
114 return AVERROR(ENOMEM);
115
116 5 avio_seek(s->pb, start_offset, SEEK_SET);
117 5 avio_read(s->pb, st->codecpar->extradata, st->codecpar->extradata_size);
118
119 5 ffio_init_checksum(s->pb, ff_crcEDB88320_update, UINT32_MAX);
120
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 5 times.
44 for (i = 0; i < c->totalframes; i++) {
121 39 uint32_t size = avio_rl32(s->pb);
122 int r;
123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
39 if (avio_feof(s->pb))
124 return AVERROR_INVALIDDATA;
125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
39 if ((r = av_add_index_entry(st, framepos, i * (int64_t)c->frame_size, size, 0,
126 AVINDEX_KEYFRAME)) < 0)
127 return r;
128 39 framepos += size;
129 }
130 5 crc = ffio_get_checksum(s->pb) ^ UINT32_MAX;
131
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
5 if (crc != avio_rl32(s->pb) && s->error_recognition & AV_EF_CRCCHECK) {
132 av_log(s, AV_LOG_ERROR, "Seek table CRC error\n");
133 return AVERROR_INVALIDDATA;
134 }
135
136 5 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
137 5 st->codecpar->codec_id = AV_CODEC_ID_TTA;
138 5 st->codecpar->ch_layout.nb_channels = channels;
139 5 st->codecpar->sample_rate = samplerate;
140 5 st->codecpar->bits_per_coded_sample = bps;
141
142
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
143 5 int64_t pos = avio_tell(s->pb);
144 5 ff_ape_parse_tag(s);
145 5 avio_seek(s->pb, pos, SEEK_SET);
146 }
147
148 5 return 0;
149 }
150
151 44 static int tta_read_packet(AVFormatContext *s, AVPacket *pkt)
152 {
153 44 TTAContext *c = s->priv_data;
154 44 AVStream *st = s->streams[0];
155 44 FFStream *const sti = ffstream(st);
156 int size, ret;
157
158 // FIXME!
159
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 39 times.
44 if (c->currentframe >= c->totalframes)
160 5 return AVERROR_EOF;
161
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (sti->nb_index_entries < c->totalframes) {
163 av_log(s, AV_LOG_ERROR, "Index entry disappeared\n");
164 return AVERROR_INVALIDDATA;
165 }
166
167 39 size = sti->index_entries[c->currentframe].size;
168
169 39 ret = av_get_packet(s->pb, pkt, size);
170 39 pkt->dts = sti->index_entries[c->currentframe++].timestamp;
171
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 34 times.
39 pkt->duration = c->currentframe == c->totalframes ? c->last_frame_size :
172 34 c->frame_size;
173 39 return ret;
174 }
175
176 static int tta_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
177 {
178 TTAContext *c = s->priv_data;
179 AVStream *st = s->streams[stream_index];
180 int index = av_index_search_timestamp(st, timestamp, flags);
181 if (index < 0)
182 return -1;
183 if (avio_seek(s->pb, ffstream(st)->index_entries[index].pos, SEEK_SET) < 0)
184 return -1;
185
186 c->currentframe = index;
187
188 return 0;
189 }
190
191 const FFInputFormat ff_tta_demuxer = {
192 .p.name = "tta",
193 .p.long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"),
194 .p.extensions = "tta",
195 .priv_data_size = sizeof(TTAContext),
196 .read_probe = tta_probe,
197 .read_header = tta_read_header,
198 .read_packet = tta_read_packet,
199 .read_seek = tta_read_seek,
200 };
201