3 * Copyright (c) 2007 Marco Gerards
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/intfloat.h"
25 #include "avio_internal.h"
29 typedef struct ThpDemuxContext
{
32 unsigned first_framesz
;
39 unsigned next_framesz
;
40 int video_stream_index
;
41 int audio_stream_index
;
43 unsigned char components
[16];
50 static int thp_probe(const AVProbeData
*p
)
53 /* check file header */
54 if (AV_RL32(p
->buf
) != MKTAG('T', 'H', 'P', '\0'))
57 d
= av_int2float(AV_RB32(p
->buf
+ 16));
58 if (d
< 0.1 || d
> 1000 || isnan(d
))
59 return AVPROBE_SCORE_MAX
/4;
61 return AVPROBE_SCORE_MAX
;
64 static int thp_read_header(AVFormatContext
*s
)
66 ThpDemuxContext
*thp
= s
->priv_data
;
68 AVIOContext
*pb
= s
->pb
;
69 int64_t fsize
= avio_size(pb
);
73 /* Read the file header. */
74 avio_rb32(pb
); /* Skip Magic. */
75 thp
->version
= avio_rb32(pb
);
77 avio_rb32(pb
); /* Max buf size. */
78 avio_rb32(pb
); /* Max samples. */
80 thp
->fps
= av_d2q(av_int2float(avio_rb32(pb
)), INT_MAX
);
81 if (thp
->fps
.den
<= 0 || thp
->fps
.num
< 0)
82 return AVERROR_INVALIDDATA
;
83 thp
->framecnt
= avio_rb32(pb
);
84 thp
->first_framesz
= avio_rb32(pb
);
85 maxsize
= avio_rb32(pb
);
86 if (fsize
> 0 && (!maxsize
|| fsize
< maxsize
))
88 ffiocontext(pb
)->maxsize
= fsize
;
90 thp
->compoff
= avio_rb32(pb
);
91 avio_rb32(pb
); /* offsetDataOffset. */
92 thp
->first_frame
= avio_rb32(pb
);
93 thp
->last_frame
= avio_rb32(pb
);
95 thp
->next_framesz
= thp
->first_framesz
;
96 thp
->next_frame
= thp
->first_frame
;
98 /* Read the component structure. */
99 avio_seek (pb
, thp
->compoff
, SEEK_SET
);
100 thp
->compcount
= avio_rb32(pb
);
102 if (thp
->compcount
> FF_ARRAY_ELEMS(thp
->components
))
103 return AVERROR_INVALIDDATA
;
105 /* Read the list of component types. */
106 avio_read(pb
, thp
->components
, 16);
108 for (i
= 0; i
< thp
->compcount
; i
++) {
109 if (thp
->components
[i
] == 0) {
113 /* Video component. */
114 st
= avformat_new_stream(s
, NULL
);
116 return AVERROR(ENOMEM
);
118 /* The denominator and numerator are switched because 1/fps
120 avpriv_set_pts_info(st
, 64, thp
->fps
.den
, thp
->fps
.num
);
121 st
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
122 st
->codecpar
->codec_id
= AV_CODEC_ID_THP
;
123 st
->codecpar
->codec_tag
= 0; /* no fourcc */
124 st
->codecpar
->width
= avio_rb32(pb
);
125 st
->codecpar
->height
= avio_rb32(pb
);
126 st
->codecpar
->sample_rate
= av_q2d(thp
->fps
);
128 st
->duration
= thp
->framecnt
;
130 thp
->video_stream_index
= st
->index
;
132 if (thp
->version
== 0x11000)
133 avio_rb32(pb
); /* Unknown. */
134 } else if (thp
->components
[i
] == 1) {
135 if (thp
->has_audio
!= 0)
138 /* Audio component. */
139 st
= avformat_new_stream(s
, NULL
);
141 return AVERROR(ENOMEM
);
143 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
144 st
->codecpar
->codec_id
= AV_CODEC_ID_ADPCM_THP
;
145 st
->codecpar
->codec_tag
= 0; /* no fourcc */
146 st
->codecpar
->ch_layout
.nb_channels
= avio_rb32(pb
);
147 st
->codecpar
->sample_rate
= avio_rb32(pb
); /* Frequency. */
148 st
->duration
= avio_rb32(pb
);
150 avpriv_set_pts_info(st
, 64, 1, st
->codecpar
->sample_rate
);
152 thp
->audio_stream_index
= st
->index
;
158 return AVERROR_INVALIDDATA
;
163 static int thp_read_packet(AVFormatContext
*s
,
166 ThpDemuxContext
*thp
= s
->priv_data
;
167 AVIOContext
*pb
= s
->pb
;
171 if (thp
->audiosize
== 0) {
172 /* Terminate when last frame is reached. */
173 if (thp
->frame
>= thp
->framecnt
)
176 avio_seek(pb
, thp
->next_frame
, SEEK_SET
);
178 /* Locate the next frame and read out its size. */
179 thp
->next_frame
+= FFMAX(thp
->next_framesz
, 1);
180 thp
->next_framesz
= avio_rb32(pb
);
182 avio_rb32(pb
); /* Previous total size. */
183 size
= avio_rb32(pb
); /* Total size of this frame. */
185 /* Store the audiosize so the next time this function is called,
186 the audio can be read. */
188 thp
->audiosize
= avio_rb32(pb
); /* Audio size. */
192 ret
= av_get_packet(pb
, pkt
, size
);
196 return AVERROR_INVALIDDATA
;
199 pkt
->stream_index
= thp
->video_stream_index
;
201 ret
= av_get_packet(pb
, pkt
, thp
->audiosize
);
204 if (ret
!= thp
->audiosize
) {
205 return AVERROR_INVALIDDATA
;
208 pkt
->stream_index
= thp
->audio_stream_index
;
209 if (thp
->audiosize
>= 8)
210 pkt
->duration
= AV_RB32(&pkt
->data
[4]);
219 const FFInputFormat ff_thp_demuxer
= {
221 .p
.long_name
= NULL_IF_CONFIG_SMALL("THP"),
222 .priv_data_size
= sizeof(ThpDemuxContext
),
223 .read_probe
= thp_probe
,
224 .read_header
= thp_read_header
,
225 .read_packet
= thp_read_packet