Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
thp.c
Go to the documentation of this file.
1
/*
2
* THP Demuxer
3
* Copyright (c) 2007 Marco Gerards
4
*
5
* This file is part of Libav.
6
*
7
* Libav 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
* Libav 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 Libav; 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/intfloat.h
"
24
#include "
avformat.h
"
25
#include "
internal.h
"
26
27
typedef
struct
ThpDemuxContext
{
28
int
version
;
29
int
first_frame
;
30
int
first_framesz
;
31
int
last_frame
;
32
int
compoff
;
33
int
framecnt
;
34
AVRational
fps
;
35
int
frame
;
36
int
next_frame
;
37
int
next_framesz
;
38
int
video_stream_index
;
39
int
audio_stream_index
;
40
int
compcount
;
41
unsigned
char
components
[16];
42
AVStream
*
vst
;
43
int
has_audio
;
44
int
audiosize
;
45
}
ThpDemuxContext
;
46
47
48
static
int
thp_probe
(
AVProbeData
*p)
49
{
50
/* check file header */
51
if
(
AV_RL32
(p->
buf
) ==
MKTAG
(
'T'
,
'H'
,
'P'
,
'\0'
))
52
return
AVPROBE_SCORE_MAX
;
53
else
54
return
0;
55
}
56
57
static
int
thp_read_header
(
AVFormatContext
*s,
58
AVFormatParameters
*ap)
59
{
60
ThpDemuxContext
*thp = s->
priv_data
;
61
AVStream
*st;
62
AVIOContext
*pb = s->
pb
;
63
int
i;
64
65
/* Read the file header. */
66
avio_rb32
(pb);
/* Skip Magic. */
67
thp->
version
=
avio_rb32
(pb);
68
69
avio_rb32
(pb);
/* Max buf size. */
70
avio_rb32
(pb);
/* Max samples. */
71
72
thp->
fps
=
av_d2q
(
av_int2float
(
avio_rb32
(pb)), INT_MAX);
73
thp->
framecnt
=
avio_rb32
(pb);
74
thp->
first_framesz
=
avio_rb32
(pb);
75
avio_rb32
(pb);
/* Data size. */
76
77
thp->
compoff
=
avio_rb32
(pb);
78
avio_rb32
(pb);
/* offsetDataOffset. */
79
thp->
first_frame
=
avio_rb32
(pb);
80
thp->
last_frame
=
avio_rb32
(pb);
81
82
thp->
next_framesz
= thp->
first_framesz
;
83
thp->
next_frame
= thp->
first_frame
;
84
85
/* Read the component structure. */
86
avio_seek
(pb, thp->
compoff
, SEEK_SET);
87
thp->
compcount
=
avio_rb32
(pb);
88
89
/* Read the list of component types. */
90
avio_read
(pb, thp->
components
, 16);
91
92
for
(i = 0; i < thp->
compcount
; i++) {
93
if
(thp->
components
[i] == 0) {
94
if
(thp->
vst
!= 0)
95
break
;
96
97
/* Video component. */
98
st =
avformat_new_stream
(s,
NULL
);
99
if
(!st)
100
return
AVERROR
(ENOMEM);
101
102
/* The denominator and numerator are switched because 1/fps
103
is required. */
104
avpriv_set_pts_info
(st, 64, thp->
fps
.
den
, thp->
fps
.
num
);
105
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
106
st->
codec
->
codec_id
=
CODEC_ID_THP
;
107
st->
codec
->
codec_tag
= 0;
/* no fourcc */
108
st->
codec
->
width
=
avio_rb32
(pb);
109
st->
codec
->
height
=
avio_rb32
(pb);
110
st->
codec
->
sample_rate
=
av_q2d
(thp->
fps
);
111
thp->
vst
= st;
112
thp->
video_stream_index
= st->
index
;
113
114
if
(thp->
version
== 0x11000)
115
avio_rb32
(pb);
/* Unknown. */
116
}
else
if
(thp->
components
[i] == 1) {
117
if
(thp->
has_audio
!= 0)
118
break
;
119
120
/* Audio component. */
121
st =
avformat_new_stream
(s,
NULL
);
122
if
(!st)
123
return
AVERROR
(ENOMEM);
124
125
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
126
st->
codec
->
codec_id
=
CODEC_ID_ADPCM_THP
;
127
st->
codec
->
codec_tag
= 0;
/* no fourcc */
128
st->
codec
->
channels
=
avio_rb32
(pb);
/* numChannels. */
129
st->
codec
->
sample_rate
=
avio_rb32
(pb);
/* Frequency. */
130
131
avpriv_set_pts_info
(st, 64, 1, st->
codec
->
sample_rate
);
132
133
thp->
audio_stream_index
= st->
index
;
134
thp->
has_audio
= 1;
135
}
136
}
137
138
return
0;
139
}
140
141
static
int
thp_read_packet
(
AVFormatContext
*s,
142
AVPacket
*pkt)
143
{
144
ThpDemuxContext
*thp = s->
priv_data
;
145
AVIOContext
*pb = s->
pb
;
146
int
size
;
147
int
ret;
148
149
if
(thp->
audiosize
== 0) {
150
/* Terminate when last frame is reached. */
151
if
(thp->
frame
>= thp->
framecnt
)
152
return
AVERROR
(EIO);
153
154
avio_seek
(pb, thp->
next_frame
, SEEK_SET);
155
156
/* Locate the next frame and read out its size. */
157
thp->
next_frame
+= thp->
next_framesz
;
158
thp->
next_framesz
=
avio_rb32
(pb);
159
160
avio_rb32
(pb);
/* Previous total size. */
161
size =
avio_rb32
(pb);
/* Total size of this frame. */
162
163
/* Store the audiosize so the next time this function is called,
164
the audio can be read. */
165
if
(thp->
has_audio
)
166
thp->
audiosize
=
avio_rb32
(pb);
/* Audio size. */
167
else
168
thp->
frame
++;
169
170
ret =
av_get_packet
(pb, pkt, size);
171
if
(ret != size) {
172
av_free_packet
(pkt);
173
return
AVERROR
(EIO);
174
}
175
176
pkt->
stream_index
= thp->
video_stream_index
;
177
}
else
{
178
ret =
av_get_packet
(pb, pkt, thp->
audiosize
);
179
if
(ret != thp->
audiosize
) {
180
av_free_packet
(pkt);
181
return
AVERROR
(EIO);
182
}
183
184
pkt->
stream_index
= thp->
audio_stream_index
;
185
thp->
audiosize
= 0;
186
thp->
frame
++;
187
}
188
189
return
0;
190
}
191
192
AVInputFormat
ff_thp_demuxer
= {
193
.
name
=
"thp"
,
194
.long_name =
NULL_IF_CONFIG_SMALL
(
"THP"
),
195
.priv_data_size =
sizeof
(
ThpDemuxContext
),
196
.
read_probe
=
thp_probe
,
197
.
read_header
=
thp_read_header
,
198
.
read_packet
=
thp_read_packet
199
};