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"
25 typedef struct ThpDemuxContext
{
36 int video_stream_index
;
37 int audio_stream_index
;
39 unsigned char components
[16];
46 static int thp_probe(AVProbeData
*p
)
48 /* check file header */
49 if (AV_RL32(p
->buf
) == MKTAG('T', 'H', 'P', '\0'))
50 return AVPROBE_SCORE_MAX
;
55 static int thp_read_header(AVFormatContext
*s
,
56 AVFormatParameters
*ap
)
58 ThpDemuxContext
*thp
= s
->priv_data
;
60 ByteIOContext
*pb
= s
->pb
;
63 /* Read the file header. */
64 get_be32(pb
); /* Skip Magic. */
65 thp
->version
= get_be32(pb
);
67 get_be32(pb
); /* Max buf size. */
68 get_be32(pb
); /* Max samples. */
70 thp
->fps
= av_d2q(av_int2flt(get_be32(pb
)), INT_MAX
);
71 thp
->framecnt
= get_be32(pb
);
72 thp
->first_framesz
= get_be32(pb
);
73 get_be32(pb
); /* Data size. */
75 thp
->compoff
= get_be32(pb
);
76 get_be32(pb
); /* offsetDataOffset. */
77 thp
->first_frame
= get_be32(pb
);
78 thp
->last_frame
= get_be32(pb
);
80 thp
->next_framesz
= thp
->first_framesz
;
81 thp
->next_frame
= thp
->first_frame
;
83 /* Read the component structure. */
84 url_fseek (pb
, thp
->compoff
, SEEK_SET
);
85 thp
->compcount
= get_be32(pb
);
87 /* Read the list of component types. */
88 get_buffer(pb
, thp
->components
, 16);
90 for (i
= 0; i
< thp
->compcount
; i
++) {
91 if (thp
->components
[i
] == 0) {
95 /* Video component. */
96 st
= av_new_stream(s
, 0);
98 return AVERROR(ENOMEM
);
100 /* The denominator and numerator are switched because 1/fps
102 av_set_pts_info(st
, 64, thp
->fps
.den
, thp
->fps
.num
);
103 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
104 st
->codec
->codec_id
= CODEC_ID_THP
;
105 st
->codec
->codec_tag
= 0; /* no fourcc */
106 st
->codec
->width
= get_be32(pb
);
107 st
->codec
->height
= get_be32(pb
);
108 st
->codec
->sample_rate
= av_q2d(thp
->fps
);
110 thp
->video_stream_index
= st
->index
;
112 if (thp
->version
== 0x11000)
113 get_be32(pb
); /* Unknown. */
114 } else if (thp
->components
[i
] == 1) {
115 if (thp
->has_audio
!= 0)
118 /* Audio component. */
119 st
= av_new_stream(s
, 0);
121 return AVERROR(ENOMEM
);
123 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
124 st
->codec
->codec_id
= CODEC_ID_ADPCM_THP
;
125 st
->codec
->codec_tag
= 0; /* no fourcc */
126 st
->codec
->channels
= get_be32(pb
); /* numChannels. */
127 st
->codec
->sample_rate
= get_be32(pb
); /* Frequency. */
129 av_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
131 thp
->audio_stream_index
= st
->index
;
139 static int thp_read_packet(AVFormatContext
*s
,
142 ThpDemuxContext
*thp
= s
->priv_data
;
143 ByteIOContext
*pb
= s
->pb
;
147 if (thp
->audiosize
== 0) {
148 /* Terminate when last frame is reached. */
149 if (thp
->frame
>= thp
->framecnt
)
152 url_fseek(pb
, thp
->next_frame
, SEEK_SET
);
154 /* Locate the next frame and read out its size. */
155 thp
->next_frame
+= thp
->next_framesz
;
156 thp
->next_framesz
= get_be32(pb
);
158 get_be32(pb
); /* Previous total size. */
159 size
= get_be32(pb
); /* Total size of this frame. */
161 /* Store the audiosize so the next time this function is called,
162 the audio can be read. */
164 thp
->audiosize
= get_be32(pb
); /* Audio size. */
168 ret
= av_get_packet(pb
, pkt
, size
);
174 pkt
->stream_index
= thp
->video_stream_index
;
176 ret
= av_get_packet(pb
, pkt
, thp
->audiosize
);
177 if (ret
!= thp
->audiosize
) {
182 pkt
->stream_index
= thp
->audio_stream_index
;
190 AVInputFormat thp_demuxer
= {
192 NULL_IF_CONFIG_SMALL("THP"),
193 sizeof(ThpDemuxContext
),