Coverage Report

Created: 2025-11-16 07:20

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.50k
#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
964k
#define DTSHDHDR 0x4454534844484452
38
#define EXTSS_MD 0x45585453535f4d44
39
391
#define FILEINFO 0x46494C45494E464F
40
#define NAVI_TBL 0x4E4156492D54424C
41
5.12k
#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
964k
{
50
964k
    if (AV_RB64(p->buf) == DTSHDHDR)
51
161
        return AVPROBE_SCORE_MAX;
52
964k
    return 0;
53
964k
}
54
55
static int dtshd_read_header(AVFormatContext *s)
56
5.89k
{
57
5.89k
    DTSHDDemuxContext *dtshd = s->priv_data;
58
5.89k
    AVIOContext *pb = s->pb;
59
5.89k
    uint64_t chunk_type, chunk_size;
60
5.89k
    int64_t duration, orig_nb_samples, data_start;
61
5.89k
    AVStream *st;
62
5.89k
    int ret;
63
5.89k
    char *value;
64
65
5.89k
    st = avformat_new_stream(s, NULL);
66
5.89k
    if (!st)
67
0
        return AVERROR(ENOMEM);
68
5.89k
    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
69
5.89k
    st->codecpar->codec_id   = AV_CODEC_ID_DTS;
70
5.89k
    ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;
71
72
10.3k
    for (;;) {
73
10.3k
        chunk_type = avio_rb64(pb);
74
10.3k
        chunk_size = avio_rb64(pb);
75
76
10.3k
        if (avio_feof(pb))
77
760
            break;
78
79
9.59k
        if (chunk_size < 4) {
80
6
            av_log(s, AV_LOG_ERROR, "chunk size too small\n");
81
6
            return AVERROR_INVALIDDATA;
82
6
        }
83
9.59k
        if (chunk_size > ((uint64_t)1 << 61)) {
84
92
            av_log(s, AV_LOG_ERROR, "chunk size too big\n");
85
92
            return AVERROR_INVALIDDATA;
86
92
        }
87
88
9.49k
        switch (chunk_type) {
89
5.12k
        case STRMDATA:
90
5.12k
            data_start = avio_tell(pb);
91
5.12k
            dtshd->data_end = data_start + chunk_size;
92
5.12k
            if (dtshd->data_end <= chunk_size)
93
0
                return AVERROR_INVALIDDATA;
94
5.12k
            if (!(pb->seekable & AVIO_SEEKABLE_NORMAL))
95
4.34k
                goto break_loop;
96
781
            goto skip;
97
781
            break;
98
2.50k
        case AUPR_HDR:
99
2.50k
            if (chunk_size < 21)
100
5
                return AVERROR_INVALIDDATA;
101
2.49k
            avio_skip(pb, 3);
102
2.49k
            st->codecpar->sample_rate = avio_rb24(pb);
103
2.49k
            if (!st->codecpar->sample_rate)
104
54
                return AVERROR_INVALIDDATA;
105
2.44k
            duration  = avio_rb32(pb); // num_frames
106
2.44k
            duration *= avio_rb16(pb); // samples_per_frames
107
2.44k
            st->duration = duration;
108
2.44k
            orig_nb_samples  = avio_rb32(pb);
109
2.44k
            orig_nb_samples <<= 8;
110
2.44k
            orig_nb_samples |= avio_r8(pb);
111
2.44k
            st->codecpar->ch_layout.nb_channels = ff_dca_count_chs_for_mask(avio_rb16(pb));
112
2.44k
            st->codecpar->initial_padding = avio_rb16(pb);
113
2.44k
            st->codecpar->trailing_padding = FFMAX(st->duration - orig_nb_samples - st->codecpar->initial_padding, 0);
114
2.44k
            avio_skip(pb, chunk_size - 21);
115
2.44k
            break;
116
391
        case FILEINFO:
117
391
            if (chunk_size > INT_MAX)
118
42
                goto skip;
119
349
            value = av_malloc(chunk_size);
120
349
            if (!value)
121
0
                goto skip;
122
349
            avio_read(pb, value, chunk_size);
123
349
            value[chunk_size - 1] = 0;
124
349
            av_dict_set(&s->metadata, "fileinfo", value,
125
349
                        AV_DICT_DONT_STRDUP_VAL);
126
349
            break;
127
1.48k
        default:
128
2.30k
skip:
129
2.30k
            ret = avio_skip(pb, chunk_size);
130
2.30k
            if (ret < 0)
131
627
                return ret;
132
9.49k
        };
133
4.46k
    }
134
135
760
    if (!dtshd->data_end)
136
441
        return AVERROR_EOF;
137
138
319
    avio_seek(pb, data_start, SEEK_SET);
139
140
4.66k
break_loop:
141
4.66k
    if (st->codecpar->sample_rate)
142
746
        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
143
144
4.66k
    return 0;
145
319
}
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
318
        return AVERROR_EOF;
157
158
117k
    ret = av_get_packet(s->pb, pkt, size);
159
117k
    if (ret < 0)
160
12.7k
        return ret;
161
162
105k
    pkt->stream_index = 0;
163
164
105k
    return ret;
165
117k
}
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
};