FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/dtshddec.c
Date: 2026-07-18 19:31:15
Exec Total Coverage
Lines: 74 90 82.2%
Functions: 3 3 100.0%
Branches: 24 38 63.2%

Line Branch Exec 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 #include "avio_internal.h"
30
31 #define AUPR_HDR 0x415550522D484452
32 #define AUPRINFO 0x41555052494E464F
33 #define BITSHVTB 0x4249545348565442
34 #define BLACKOUT 0x424C41434B4F5554
35 #define BRANCHPT 0x4252414E43485054
36 #define BUILDVER 0x4255494C44564552
37 #define CORESSMD 0x434F524553534D44
38 #define DTSHDHDR 0x4454534844484452
39 #define EXTSS_MD 0x45585453535f4d44
40 #define FILEINFO 0x46494C45494E464F
41 #define NAVI_TBL 0x4E4156492D54424C
42 #define STRMDATA 0x5354524D44415441
43 #define TIMECODE 0x54494D45434F4445
44
45 typedef struct DTSHDDemuxContext {
46 uint64_t data_end;
47 } DTSHDDemuxContext;
48
49 7778 static int dtshd_probe(const AVProbeData *p)
50 {
51
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 7734 times.
7778 if (AV_RB64(p->buf) == DTSHDHDR)
52 44 return AVPROBE_SCORE_MAX;
53 7734 return 0;
54 }
55
56 71 static int dtshd_read_header(AVFormatContext *s)
57 {
58 71 DTSHDDemuxContext *dtshd = s->priv_data;
59 71 AVIOContext *pb = s->pb;
60 uint64_t chunk_type, chunk_size;
61 int64_t duration, orig_nb_samples, data_start;
62 AVStream *st;
63 FFStream *sti;
64 int ret;
65 char *value;
66
67 71 st = avformat_new_stream(s, NULL);
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!st)
69 return AVERROR(ENOMEM);
70 71 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
71 71 st->codecpar->codec_id = AV_CODEC_ID_DTS;
72 71 sti = ffstream(st);
73 71 sti->need_parsing = AVSTREAM_PARSE_FULL_RAW;
74
75 for (;;) {
76 680 chunk_type = avio_rb64(pb);
77 680 chunk_size = avio_rb64(pb);
78
79
2/2
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 609 times.
680 if (avio_feof(pb))
80 71 break;
81
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 609 times.
609 if (chunk_size < 4) {
83 av_log(s, AV_LOG_ERROR, "chunk size too small\n");
84 return AVERROR_INVALIDDATA;
85 }
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 609 times.
609 if (chunk_size > ((uint64_t)1 << 61)) {
87 av_log(s, AV_LOG_ERROR, "chunk size too big\n");
88 return AVERROR_INVALIDDATA;
89 }
90
91
4/4
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 396 times.
609 switch (chunk_type) {
92 71 case STRMDATA:
93 71 data_start = avio_tell(pb);
94 71 dtshd->data_end = data_start + chunk_size;
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (dtshd->data_end <= chunk_size)
96 return AVERROR_INVALIDDATA;
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL))
98 goto break_loop;
99 71 goto skip;
100 break;
101 71 case AUPR_HDR:
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (chunk_size < 21)
103 return AVERROR_INVALIDDATA;
104 71 avio_skip(pb, 3);
105 71 st->codecpar->sample_rate = avio_rb24(pb);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!st->codecpar->sample_rate)
107 return AVERROR_INVALIDDATA;
108 71 duration = avio_rb32(pb); // num_frames
109 71 duration *= avio_rb16(pb); // samples_per_frames
110 71 st->duration = duration;
111 71 orig_nb_samples = avio_rb32(pb);
112 71 orig_nb_samples <<= 8;
113 71 orig_nb_samples |= avio_r8(pb);
114 71 st->codecpar->ch_layout.nb_channels = ff_dca_count_chs_for_mask(avio_rb16(pb));
115 71 st->codecpar->initial_padding = avio_rb16(pb);
116 71 st->codecpar->trailing_padding = FFMAX(st->duration - orig_nb_samples - st->codecpar->initial_padding, 0);
117 71 st->start_time =
118 71 sti->start_skip_samples = st->codecpar->initial_padding;
119 71 sti->first_discard_sample = orig_nb_samples + st->codecpar->initial_padding;
120 71 sti->last_discard_sample = st->duration;
121 71 avio_skip(pb, chunk_size - 21);
122 71 break;
123 71 case FILEINFO:
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (chunk_size > INT_MAX)
125 goto skip;
126 71 value = av_malloc(chunk_size);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!value)
128 goto skip;
129 71 ret = ffio_read_size(pb, value, chunk_size);
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (ret < 0) {
131 av_free(value);
132 goto skip;
133 }
134 71 value[chunk_size - 1] = 0;
135 71 av_dict_set(&s->metadata, "fileinfo", value,
136 AV_DICT_DONT_STRDUP_VAL);
137 71 break;
138 default:
139 467 skip:
140 467 ret = avio_skip(pb, chunk_size);
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 467 times.
467 if (ret < 0)
142 return ret;
143 };
144 }
145
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (!dtshd->data_end)
147 return AVERROR_EOF;
148
149 71 avio_seek(pb, data_start, SEEK_SET);
150
151 71 break_loop:
152
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 if (st->codecpar->sample_rate)
153 71 avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
154
155 71 return 0;
156 }
157
158 2533 static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
159 {
160 2533 DTSHDDemuxContext *dtshd = s->priv_data;
161 int64_t size, left;
162 int ret;
163
164 2533 left = dtshd->data_end - avio_tell(s->pb);
165 2533 size = FFMIN(left, 1024);
166
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 2320 times.
2533 if (size <= 0)
167 213 return AVERROR_EOF;
168
169 2320 ret = av_get_packet(s->pb, pkt, size);
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2320 times.
2320 if (ret < 0)
171 return ret;
172
173 2320 pkt->stream_index = 0;
174
175 2320 return ret;
176 }
177
178 const FFInputFormat ff_dtshd_demuxer = {
179 .p.name = "dtshd",
180 .p.long_name = NULL_IF_CONFIG_SMALL("raw DTS-HD"),
181 .p.flags = AVFMT_GENERIC_INDEX,
182 .p.extensions = "dtshd",
183 .priv_data_size = sizeof(DTSHDDemuxContext),
184 .read_probe = dtshd_probe,
185 .read_header = dtshd_read_header,
186 .read_packet = raw_read_packet,
187 .raw_codec_id = AV_CODEC_ID_DTS,
188 };
189