FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/dtshddec.c
Date: 2026-04-23 02:20:26
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 7474 static int dtshd_probe(const AVProbeData *p)
50 {
51
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 7432 times.
7474 if (AV_RB64(p->buf) == DTSHDHDR)
52 42 return AVPROBE_SCORE_MAX;
53 7432 return 0;
54 }
55
56 69 static int dtshd_read_header(AVFormatContext *s)
57 {
58 69 DTSHDDemuxContext *dtshd = s->priv_data;
59 69 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 69 st = avformat_new_stream(s, NULL);
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (!st)
69 return AVERROR(ENOMEM);
70 69 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
71 69 st->codecpar->codec_id = AV_CODEC_ID_DTS;
72 69 sti = ffstream(st);
73 69 sti->need_parsing = AVSTREAM_PARSE_FULL_RAW;
74
75 for (;;) {
76 662 chunk_type = avio_rb64(pb);
77 662 chunk_size = avio_rb64(pb);
78
79
2/2
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 593 times.
662 if (avio_feof(pb))
80 69 break;
81
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
593 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 593 times.
593 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 69 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 386 times.
593 switch (chunk_type) {
92 69 case STRMDATA:
93 69 data_start = avio_tell(pb);
94 69 dtshd->data_end = data_start + chunk_size;
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (dtshd->data_end <= chunk_size)
96 return AVERROR_INVALIDDATA;
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL))
98 goto break_loop;
99 69 goto skip;
100 break;
101 69 case AUPR_HDR:
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (chunk_size < 21)
103 return AVERROR_INVALIDDATA;
104 69 avio_skip(pb, 3);
105 69 st->codecpar->sample_rate = avio_rb24(pb);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (!st->codecpar->sample_rate)
107 return AVERROR_INVALIDDATA;
108 69 duration = avio_rb32(pb); // num_frames
109 69 duration *= avio_rb16(pb); // samples_per_frames
110 69 st->duration = duration;
111 69 orig_nb_samples = avio_rb32(pb);
112 69 orig_nb_samples <<= 8;
113 69 orig_nb_samples |= avio_r8(pb);
114 69 st->codecpar->ch_layout.nb_channels = ff_dca_count_chs_for_mask(avio_rb16(pb));
115 69 st->codecpar->initial_padding = avio_rb16(pb);
116 69 st->codecpar->trailing_padding = FFMAX(st->duration - orig_nb_samples - st->codecpar->initial_padding, 0);
117 69 st->start_time =
118 69 sti->start_skip_samples = st->codecpar->initial_padding;
119 69 sti->first_discard_sample = orig_nb_samples + st->codecpar->initial_padding;
120 69 sti->last_discard_sample = st->duration;
121 69 avio_skip(pb, chunk_size - 21);
122 69 break;
123 69 case FILEINFO:
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (chunk_size > INT_MAX)
125 goto skip;
126 69 value = av_malloc(chunk_size);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (!value)
128 goto skip;
129 69 ret = ffio_read_size(pb, value, chunk_size);
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (ret < 0) {
131 av_free(value);
132 goto skip;
133 }
134 69 value[chunk_size - 1] = 0;
135 69 av_dict_set(&s->metadata, "fileinfo", value,
136 AV_DICT_DONT_STRDUP_VAL);
137 69 break;
138 default:
139 455 skip:
140 455 ret = avio_skip(pb, chunk_size);
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455 times.
455 if (ret < 0)
142 return ret;
143 };
144 }
145
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (!dtshd->data_end)
147 return AVERROR_EOF;
148
149 69 avio_seek(pb, data_start, SEEK_SET);
150
151 69 break_loop:
152
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 if (st->codecpar->sample_rate)
153 69 avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
154
155 69 return 0;
156 }
157
158 2497 static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
159 {
160 2497 DTSHDDemuxContext *dtshd = s->priv_data;
161 int64_t size, left;
162 int ret;
163
164 2497 left = dtshd->data_end - avio_tell(s->pb);
165 2497 size = FFMIN(left, 1024);
166
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 2290 times.
2497 if (size <= 0)
167 207 return AVERROR_EOF;
168
169 2290 ret = av_get_packet(s->pb, pkt, size);
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2290 times.
2290 if (ret < 0)
171 return ret;
172
173 2290 pkt->stream_index = 0;
174
175 2290 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