Coverage Report

Created: 2025-12-31 07:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/dtshddec.c
Line
Count
Source
1
/*
2
 * Raw DTS-HD demuxer
3
 * Copyright (c) 2012 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 "libavutil/intreadwrite.h"
23
#include "libavutil/dict.h"
24
#include "libavutil/mem.h"
25
#include "libavcodec/dca.h"
26
#include "avformat.h"
27
#include "demux.h"
28
#include "internal.h"
29
30
2.79k
#define AUPR_HDR 0x415550522D484452
31
#define AUPRINFO 0x41555052494E464F
32
#define BITSHVTB 0x4249545348565442
33
#define BLACKOUT 0x424C41434B4F5554
34
#define BRANCHPT 0x4252414E43485054
35
#define BUILDVER 0x4255494C44564552
36
#define CORESSMD 0x434F524553534D44
37
942k
#define DTSHDHDR 0x4454534844484452
38
#define EXTSS_MD 0x45585453535f4d44
39
599
#define FILEINFO 0x46494C45494E464F
40
#define NAVI_TBL 0x4E4156492D54424C
41
6.04k
#define STRMDATA 0x5354524D44415441
42
#define TIMECODE 0x54494D45434F4445
43
44
typedef struct DTSHDDemuxContext {
45
    uint64_t    data_end;
46
} DTSHDDemuxContext;
47
48
static int dtshd_probe(const AVProbeData *p)
49
942k
{
50
942k
    if (AV_RB64(p->buf) == DTSHDHDR)
51
149
        return AVPROBE_SCORE_MAX;
52
942k
    return 0;
53
942k
}
54
55
static int dtshd_read_header(AVFormatContext *s)
56
6.46k
{
57
6.46k
    DTSHDDemuxContext *dtshd = s->priv_data;
58
6.46k
    AVIOContext *pb = s->pb;
59
6.46k
    uint64_t chunk_type, chunk_size;
60
6.46k
    int64_t duration, orig_nb_samples, data_start;
61
6.46k
    AVStream *st;
62
6.46k
    int ret;
63
6.46k
    char *value;
64
65
6.46k
    st = avformat_new_stream(s, NULL);
66
6.46k
    if (!st)
67
0
        return AVERROR(ENOMEM);
68
6.46k
    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
69
6.46k
    st->codecpar->codec_id   = AV_CODEC_ID_DTS;
70
6.46k
    ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;
71
72
11.8k
    for (;;) {
73
11.8k
        chunk_type = avio_rb64(pb);
74
11.8k
        chunk_size = avio_rb64(pb);
75
76
11.8k
        if (avio_feof(pb))
77
761
            break;
78
79
11.1k
        if (chunk_size < 4) {
80
7
            av_log(s, AV_LOG_ERROR, "chunk size too small\n");
81
7
            return AVERROR_INVALIDDATA;
82
7
        }
83
11.0k
        if (chunk_size > ((uint64_t)1 << 61)) {
84
109
            av_log(s, AV_LOG_ERROR, "chunk size too big\n");
85
109
            return AVERROR_INVALIDDATA;
86
109
        }
87
88
10.9k
        switch (chunk_type) {
89
6.04k
        case STRMDATA:
90
6.04k
            data_start = avio_tell(pb);
91
6.04k
            dtshd->data_end = data_start + chunk_size;
92
6.04k
            if (dtshd->data_end <= chunk_size)
93
0
                return AVERROR_INVALIDDATA;
94
6.04k
            if (!(pb->seekable & AVIO_SEEKABLE_NORMAL))
95
4.91k
                goto break_loop;
96
1.13k
            goto skip;
97
1.13k
            break;
98
2.79k
        case AUPR_HDR:
99
2.79k
            if (chunk_size < 21)
100
5
                return AVERROR_INVALIDDATA;
101
2.78k
            avio_skip(pb, 3);
102
2.78k
            st->codecpar->sample_rate = avio_rb24(pb);
103
2.78k
            if (!st->codecpar->sample_rate)
104
56
                return AVERROR_INVALIDDATA;
105
2.73k
            duration  = avio_rb32(pb); // num_frames
106
2.73k
            duration *= avio_rb16(pb); // samples_per_frames
107
2.73k
            st->duration = duration;
108
2.73k
            orig_nb_samples  = avio_rb32(pb);
109
2.73k
            orig_nb_samples <<= 8;
110
2.73k
            orig_nb_samples |= avio_r8(pb);
111
2.73k
            st->codecpar->ch_layout.nb_channels = ff_dca_count_chs_for_mask(avio_rb16(pb));
112
2.73k
            st->codecpar->initial_padding = avio_rb16(pb);
113
2.73k
            st->codecpar->trailing_padding = FFMAX(st->duration - orig_nb_samples - st->codecpar->initial_padding, 0);
114
2.73k
            avio_skip(pb, chunk_size - 21);
115
2.73k
            break;
116
599
        case FILEINFO:
117
599
            if (chunk_size > INT_MAX)
118
43
                goto skip;
119
556
            value = av_malloc(chunk_size);
120
556
            if (!value)
121
0
                goto skip;
122
556
            avio_read(pb, value, chunk_size);
123
556
            value[chunk_size - 1] = 0;
124
556
            av_dict_set(&s->metadata, "fileinfo", value,
125
556
                        AV_DICT_DONT_STRDUP_VAL);
126
556
            break;
127
1.55k
        default:
128
2.73k
skip:
129
2.73k
            ret = avio_skip(pb, chunk_size);
130
2.73k
            if (ret < 0)
131
618
                return ret;
132
10.9k
        };
133
5.40k
    }
134
135
761
    if (!dtshd->data_end)
136
434
        return AVERROR_EOF;
137
138
327
    avio_seek(pb, data_start, SEEK_SET);
139
140
5.23k
break_loop:
141
5.23k
    if (st->codecpar->sample_rate)
142
787
        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
143
144
5.23k
    return 0;
145
327
}
146
147
static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
148
118k
{
149
118k
    DTSHDDemuxContext *dtshd = s->priv_data;
150
118k
    int64_t size, left;
151
118k
    int ret;
152
153
118k
    left = dtshd->data_end - avio_tell(s->pb);
154
118k
    size = FFMIN(left, 1024);
155
118k
    if (size <= 0)
156
333
        return AVERROR_EOF;
157
158
118k
    ret = av_get_packet(s->pb, pkt, size);
159
118k
    if (ret < 0)
160
14.4k
        return ret;
161
162
104k
    pkt->stream_index = 0;
163
164
104k
    return ret;
165
118k
}
166
167
const FFInputFormat ff_dtshd_demuxer = {
168
    .p.name         = "dtshd",
169
    .p.long_name    = NULL_IF_CONFIG_SMALL("raw DTS-HD"),
170
    .p.flags        = AVFMT_GENERIC_INDEX,
171
    .p.extensions   = "dtshd",
172
    .priv_data_size = sizeof(DTSHDDemuxContext),
173
    .read_probe     = dtshd_probe,
174
    .read_header    = dtshd_read_header,
175
    .read_packet    = raw_read_packet,
176
    .raw_codec_id   = AV_CODEC_ID_DTS,
177
};