Coverage Report

Created: 2026-01-16 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/vqf.c
Line
Count
Source
1
/*
2
 * VQF demuxer
3
 * Copyright (c) 2009 Vitor Sessak
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 "avio_internal.h"
24
#include "demux.h"
25
#include "internal.h"
26
#include "libavutil/intreadwrite.h"
27
#include "libavutil/dict.h"
28
#include "libavutil/mathematics.h"
29
#include "libavutil/mem.h"
30
#include "metadata.h"
31
32
typedef struct VqfContext {
33
    int frame_bit_len;
34
    uint8_t last_frame_bits;
35
    int remaining_bits;
36
} VqfContext;
37
38
static int vqf_probe(const AVProbeData *probe_packet)
39
958k
{
40
958k
    if (AV_RL32(probe_packet->buf) != MKTAG('T','W','I','N'))
41
957k
        return 0;
42
43
921
    if (!memcmp(probe_packet->buf + 4, "97012000", 8))
44
187
        return AVPROBE_SCORE_MAX;
45
46
734
    if (!memcmp(probe_packet->buf + 4, "00052200", 8))
47
59
        return AVPROBE_SCORE_MAX;
48
49
675
    if (AV_RL32(probe_packet->buf + 12) > (1<<27))
50
401
        return AVPROBE_SCORE_EXTENSION/2;
51
52
274
    return AVPROBE_SCORE_EXTENSION;
53
675
}
54
55
static int add_metadata(AVFormatContext *s, uint32_t tag,
56
                         unsigned int tag_len, unsigned int remaining)
57
5.24k
{
58
5.24k
    int len = FFMIN(tag_len, remaining);
59
5.24k
    char *buf, key[5] = {0};
60
5.24k
    int ret;
61
62
5.24k
    if (len == UINT_MAX)
63
0
        return AVERROR_INVALIDDATA;
64
65
5.24k
    buf = av_malloc(len+1);
66
5.24k
    if (!buf)
67
0
        return AVERROR(ENOMEM);
68
69
5.24k
    ret = ffio_read_size(s->pb, buf, len);
70
5.24k
    if (ret < 0) {
71
964
        av_free(buf);
72
964
        return ret;
73
964
    }
74
4.28k
    buf[len] = 0;
75
4.28k
    AV_WL32(key, tag);
76
4.28k
    return av_dict_set(&s->metadata, key, buf, AV_DICT_DONT_STRDUP_VAL);
77
5.24k
}
78
79
static const AVMetadataConv vqf_metadata_conv[] = {
80
    { "(c) ", "copyright" },
81
    { "ARNG", "arranger"  },
82
    { "AUTH", "author"    },
83
    { "BAND", "band"      },
84
    { "CDCT", "conductor" },
85
    { "COMT", "comment"   },
86
    { "FILE", "filename"  },
87
    { "GENR", "genre"     },
88
    { "LABL", "publisher" },
89
    { "MUSC", "composer"  },
90
    { "NAME", "title"     },
91
    { "NOTE", "note"      },
92
    { "PROD", "producer"  },
93
    { "PRSN", "personnel" },
94
    { "REMX", "remixer"   },
95
    { "SING", "singer"    },
96
    { "TRCK", "track"     },
97
    { "WORD", "words"     },
98
    { 0 },
99
};
100
101
static int vqf_read_header(AVFormatContext *s)
102
2.28k
{
103
2.28k
    VqfContext *c = s->priv_data;
104
2.28k
    AVStream *st  = avformat_new_stream(s, NULL);
105
2.28k
    int chunk_tag;
106
2.28k
    int rate_flag = -1;
107
2.28k
    int header_size;
108
2.28k
    int read_bitrate = 0;
109
2.28k
    int size, ret;
110
2.28k
    uint8_t comm_chunk[12];
111
112
2.28k
    if (!st)
113
0
        return AVERROR(ENOMEM);
114
115
2.28k
    avio_skip(s->pb, 12);
116
117
2.28k
    header_size = avio_rb32(s->pb);
118
119
2.28k
    if (header_size < 0)
120
54
        return AVERROR_INVALIDDATA;
121
122
2.23k
    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
123
2.23k
    st->codecpar->codec_id   = AV_CODEC_ID_TWINVQ;
124
2.23k
    st->start_time = 0;
125
126
10.0k
    do {
127
10.0k
        int len;
128
10.0k
        chunk_tag = avio_rl32(s->pb);
129
130
10.0k
        if (chunk_tag == MKTAG('D','A','T','A'))
131
5
            break;
132
133
10.0k
        len = avio_rb32(s->pb);
134
135
10.0k
        if ((unsigned) len > INT_MAX/2 || header_size < 8) {
136
57
            av_log(s, AV_LOG_ERROR, "Malformed header\n");
137
57
            return -1;
138
57
        }
139
140
10.0k
        header_size -= 8;
141
142
10.0k
        switch(chunk_tag){
143
1.90k
        case MKTAG('C','O','M','M'):
144
1.90k
            if (len < 12)
145
5
                return AVERROR_INVALIDDATA;
146
147
1.90k
            ret = ffio_read_size(s->pb, comm_chunk, 12);
148
1.90k
            if (ret < 0)
149
37
                return ret;
150
1.86k
            st->codecpar->ch_layout.nb_channels = AV_RB32(comm_chunk) + 1;
151
1.86k
            read_bitrate        = AV_RB32(comm_chunk + 4);
152
1.86k
            rate_flag           = AV_RB32(comm_chunk + 8);
153
1.86k
            avio_skip(s->pb, len-12);
154
155
1.86k
            if (st->codecpar->ch_layout.nb_channels <= 0) {
156
33
                av_log(s, AV_LOG_ERROR, "Invalid number of channels\n");
157
33
                return AVERROR_INVALIDDATA;
158
33
            }
159
160
1.83k
            st->codecpar->bit_rate = (int64_t)read_bitrate * 1000;
161
1.83k
            break;
162
626
        case MKTAG('D','S','I','Z'): // size of compressed data
163
626
        {
164
626
            av_dict_set_int(&s->metadata, "size", avio_rb32(s->pb), 0);
165
626
        }
166
626
            break;
167
236
        case MKTAG('Y','E','A','R'): // recording date
168
677
        case MKTAG('E','N','C','D'): // compression date
169
1.16k
        case MKTAG('E','X','T','R'): // reserved
170
1.69k
        case MKTAG('_','Y','M','H'): // reserved
171
1.98k
        case MKTAG('_','N','T','T'): // reserved
172
2.24k
        case MKTAG('_','I','D','3'): // reserved for ID3 tags
173
2.24k
            avio_skip(s->pb, FFMIN(len, header_size));
174
2.24k
            break;
175
5.24k
        default:
176
5.24k
            ret = add_metadata(s, chunk_tag, len, header_size);
177
5.24k
            if (ret < 0)
178
964
                return ret;
179
4.28k
            break;
180
10.0k
        }
181
182
8.98k
        header_size -= len;
183
184
8.98k
    } while (header_size >= 0 && !avio_feof(s->pb));
185
186
1.13k
    switch (rate_flag) {
187
223
    case -1:
188
223
        av_log(s, AV_LOG_ERROR, "COMM tag not found!\n");
189
223
        return -1;
190
11
    case 44:
191
11
        st->codecpar->sample_rate = 44100;
192
11
        break;
193
71
    case 22:
194
71
        st->codecpar->sample_rate = 22050;
195
71
        break;
196
115
    case 11:
197
115
        st->codecpar->sample_rate = 11025;
198
115
        break;
199
718
    default:
200
718
        if (rate_flag < 8 || rate_flag > 44) {
201
89
            av_log(s, AV_LOG_ERROR, "Invalid rate flag %d\n", rate_flag);
202
89
            return AVERROR_INVALIDDATA;
203
89
        }
204
629
        st->codecpar->sample_rate = rate_flag*1000;
205
629
        break;
206
1.13k
    }
207
208
826
    if (read_bitrate / st->codecpar->ch_layout.nb_channels <  8 ||
209
796
        read_bitrate / st->codecpar->ch_layout.nb_channels > 48) {
210
52
        av_log(s, AV_LOG_ERROR, "Invalid bitrate per channel %d\n",
211
52
               read_bitrate / st->codecpar->ch_layout.nb_channels);
212
52
        return AVERROR_INVALIDDATA;
213
52
    }
214
215
774
    switch (((st->codecpar->sample_rate/1000) << 8) +
216
774
            read_bitrate/st->codecpar->ch_layout.nb_channels) {
217
43
    case (11<<8) + 8 :
218
580
    case (8 <<8) + 8 :
219
626
    case (11<<8) + 10:
220
656
    case (22<<8) + 32:
221
656
        size = 512;
222
656
        break;
223
24
    case (16<<8) + 16:
224
50
    case (22<<8) + 20:
225
54
    case (22<<8) + 24:
226
54
        size = 1024;
227
54
        break;
228
3
    case (44<<8) + 40:
229
6
    case (44<<8) + 48:
230
6
        size = 2048;
231
6
        break;
232
58
    default:
233
58
        av_log(s, AV_LOG_ERROR, "Mode not supported: %d Hz, %"PRId64" kb/s.\n",
234
58
               st->codecpar->sample_rate, st->codecpar->bit_rate);
235
58
        return -1;
236
774
    }
237
716
    c->frame_bit_len = st->codecpar->bit_rate*size/st->codecpar->sample_rate;
238
716
    avpriv_set_pts_info(st, 64, size, st->codecpar->sample_rate);
239
240
    /* put first 12 bytes of COMM chunk in extradata */
241
716
    if ((ret = ff_alloc_extradata(st->codecpar, 12)) < 0)
242
0
        return ret;
243
716
    memcpy(st->codecpar->extradata, comm_chunk, 12);
244
245
716
    ff_metadata_conv_ctx(s, NULL, vqf_metadata_conv);
246
247
716
    return 0;
248
716
}
249
250
static int vqf_read_packet(AVFormatContext *s, AVPacket *pkt)
251
377k
{
252
377k
    VqfContext *c = s->priv_data;
253
377k
    int ret;
254
377k
    int size = (c->frame_bit_len - c->remaining_bits + 7)>>3;
255
256
377k
    if ((ret = av_new_packet(pkt, size + 2)) < 0)
257
267
        return ret;
258
259
377k
    pkt->pos          = avio_tell(s->pb);
260
377k
    pkt->stream_index = 0;
261
377k
    pkt->duration     = 1;
262
263
377k
    pkt->data[0] = 8 - c->remaining_bits; // Number of bits to skip
264
377k
    pkt->data[1] = c->last_frame_bits;
265
377k
    ret = ffio_read_size(s->pb, pkt->data + 2, size);
266
377k
    if (ret < 0)
267
810
        return ret;
268
269
376k
    c->last_frame_bits = pkt->data[size+1];
270
376k
    c->remaining_bits  = (size << 3) - c->frame_bit_len + c->remaining_bits;
271
272
376k
    return 0;
273
377k
}
274
275
static int vqf_read_seek(AVFormatContext *s,
276
                         int stream_index, int64_t timestamp, int flags)
277
0
{
278
0
    VqfContext *c = s->priv_data;
279
0
    AVStream *st;
280
0
    int64_t ret;
281
0
    int64_t pos;
282
283
0
    st = s->streams[stream_index];
284
0
    pos = av_rescale_rnd(timestamp * st->codecpar->bit_rate,
285
0
                         st->time_base.num,
286
0
                         st->time_base.den * (int64_t)c->frame_bit_len,
287
0
                         (flags & AVSEEK_FLAG_BACKWARD) ?
288
0
                                                   AV_ROUND_DOWN : AV_ROUND_UP);
289
0
    pos *= c->frame_bit_len;
290
291
0
    ffstream(st)->cur_dts = av_rescale(pos, st->time_base.den,
292
0
                             st->codecpar->bit_rate * (int64_t)st->time_base.num);
293
294
0
    if ((ret = avio_seek(s->pb, ((pos-7) >> 3) + ffformatcontext(s)->data_offset, SEEK_SET)) < 0)
295
0
        return ret;
296
297
0
    c->remaining_bits = -7 - ((pos-7)&7);
298
0
    return 0;
299
0
}
300
301
const FFInputFormat ff_vqf_demuxer = {
302
    .p.name         = "vqf",
303
    .p.long_name    = NULL_IF_CONFIG_SMALL("Nippon Telegraph and Telephone Corporation (NTT) TwinVQ"),
304
    .p.extensions   = "vqf,vql,vqe",
305
    .priv_data_size = sizeof(VqfContext),
306
    .read_probe     = vqf_probe,
307
    .read_header    = vqf_read_header,
308
    .read_packet    = vqf_read_packet,
309
    .read_seek      = vqf_read_seek,
310
};