configure: Drop unused helper function test_cflags_cpp()
[libav.git] / libavformat / thp.c
CommitLineData
efb0c399
DB
1/*
2 * THP Demuxer
406792e7 3 * Copyright (c) 2007 Marco Gerards
efb0c399 4 *
2912e87a 5 * This file is part of Libav.
efb0c399 6 *
2912e87a 7 * Libav is free software; you can redistribute it and/or
efb0c399
DB
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 *
2912e87a 12 * Libav is distributed in the hope that it will be useful,
efb0c399
DB
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
2912e87a 18 * License along with Libav; if not, write to the Free Software
efb0c399
DB
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
6a5d31ac 22#include "libavutil/intreadwrite.h"
3383a53e 23#include "libavutil/intfloat.h"
efb0c399 24#include "avformat.h"
c3f9ebf7 25#include "internal.h"
efb0c399
DB
26
27typedef 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;
d1e0d21f 39 int audio_stream_index;
efb0c399
DB
40 int compcount;
41 unsigned char components[16];
42 AVStream* vst;
43 int has_audio;
d1e0d21f 44 int audiosize;
efb0c399
DB
45} ThpDemuxContext;
46
47
48static int thp_probe(AVProbeData *p)
49{
50 /* check file header */
efb0c399
DB
51 if (AV_RL32(p->buf) == MKTAG('T', 'H', 'P', '\0'))
52 return AVPROBE_SCORE_MAX;
53 else
54 return 0;
55}
56
6e9651d1 57static int thp_read_header(AVFormatContext *s)
efb0c399 58{
90f2a1a0
MG
59 ThpDemuxContext *thp = s->priv_data;
60 AVStream *st;
ae628ec1 61 AVIOContext *pb = s->pb;
90f2a1a0
MG
62 int i;
63
64 /* Read the file header. */
b7effd4e
AK
65 avio_rb32(pb); /* Skip Magic. */
66 thp->version = avio_rb32(pb);
90f2a1a0 67
b7effd4e
AK
68 avio_rb32(pb); /* Max buf size. */
69 avio_rb32(pb); /* Max samples. */
90f2a1a0 70
3383a53e 71 thp->fps = av_d2q(av_int2float(avio_rb32(pb)), INT_MAX);
b7effd4e
AK
72 thp->framecnt = avio_rb32(pb);
73 thp->first_framesz = avio_rb32(pb);
74 avio_rb32(pb); /* Data size. */
90f2a1a0 75
b7effd4e
AK
76 thp->compoff = avio_rb32(pb);
77 avio_rb32(pb); /* offsetDataOffset. */
78 thp->first_frame = avio_rb32(pb);
79 thp->last_frame = avio_rb32(pb);
90f2a1a0
MG
80
81 thp->next_framesz = thp->first_framesz;
82 thp->next_frame = thp->first_frame;
83
84 /* Read the component structure. */
6b4aa5da 85 avio_seek (pb, thp->compoff, SEEK_SET);
b7effd4e 86 thp->compcount = avio_rb32(pb);
90f2a1a0
MG
87
88 /* Read the list of component types. */
b7effd4e 89 avio_read(pb, thp->components, 16);
90f2a1a0
MG
90
91 for (i = 0; i < thp->compcount; i++) {
92 if (thp->components[i] == 0) {
93 if (thp->vst != 0)
94 break;
95
96 /* Video component. */
3b3bbdd3 97 st = avformat_new_stream(s, NULL);
90f2a1a0 98 if (!st)
769e10f0 99 return AVERROR(ENOMEM);
90f2a1a0
MG
100
101 /* The denominator and numerator are switched because 1/fps
102 is required. */
c3f9ebf7 103 avpriv_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
9200514a
AK
104 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
105 st->codecpar->codec_id = AV_CODEC_ID_THP;
106 st->codecpar->codec_tag = 0; /* no fourcc */
107 st->codecpar->width = avio_rb32(pb);
108 st->codecpar->height = avio_rb32(pb);
109 st->codecpar->sample_rate = av_q2d(thp->fps);
90f2a1a0
MG
110 thp->vst = st;
111 thp->video_stream_index = st->index;
112
113 if (thp->version == 0x11000)
b7effd4e 114 avio_rb32(pb); /* Unknown. */
90f2a1a0
MG
115 } else if (thp->components[i] == 1) {
116 if (thp->has_audio != 0)
117 break;
118
119 /* Audio component. */
3b3bbdd3 120 st = avformat_new_stream(s, NULL);
90f2a1a0 121 if (!st)
769e10f0 122 return AVERROR(ENOMEM);
90f2a1a0 123
9200514a
AK
124 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
125 st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP;
126 st->codecpar->codec_tag = 0; /* no fourcc */
127 st->codecpar->channels = avio_rb32(pb); /* numChannels. */
128 st->codecpar->sample_rate = avio_rb32(pb); /* Frequency. */
5f2c8315 129 st->duration = avio_rb32(pb);
90f2a1a0 130
9200514a 131 avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
90f2a1a0
MG
132
133 thp->audio_stream_index = st->index;
134 thp->has_audio = 1;
efb0c399 135 }
efb0c399
DB
136 }
137
90f2a1a0 138 return 0;
efb0c399
DB
139}
140
141static int thp_read_packet(AVFormatContext *s,
142 AVPacket *pkt)
143{
144 ThpDemuxContext *thp = s->priv_data;
ae628ec1 145 AVIOContext *pb = s->pb;
efb0c399
DB
146 int size;
147 int ret;
148
d1e0d21f 149 if (thp->audiosize == 0) {
90f2a1a0
MG
150 /* Terminate when last frame is reached. */
151 if (thp->frame >= thp->framecnt)
6f3e0b21 152 return AVERROR(EIO);
d1e0d21f 153
6b4aa5da 154 avio_seek(pb, thp->next_frame, SEEK_SET);
efb0c399 155
90f2a1a0
MG
156 /* Locate the next frame and read out its size. */
157 thp->next_frame += thp->next_framesz;
b7effd4e 158 thp->next_framesz = avio_rb32(pb);
efb0c399 159
b7effd4e
AK
160 avio_rb32(pb); /* Previous total size. */
161 size = avio_rb32(pb); /* Total size of this frame. */
efb0c399 162
90f2a1a0
MG
163 /* Store the audiosize so the next time this function is called,
164 the audio can be read. */
165 if (thp->has_audio)
b7effd4e 166 thp->audiosize = avio_rb32(pb); /* Audio size. */
90f2a1a0
MG
167 else
168 thp->frame++;
efb0c399 169
90f2a1a0
MG
170 ret = av_get_packet(pb, pkt, size);
171 if (ret != size) {
ce70f28a 172 av_packet_unref(pkt);
6f3e0b21 173 return AVERROR(EIO);
90f2a1a0 174 }
efb0c399 175
90f2a1a0
MG
176 pkt->stream_index = thp->video_stream_index;
177 } else {
d1e0d21f
MG
178 ret = av_get_packet(pb, pkt, thp->audiosize);
179 if (ret != thp->audiosize) {
ce70f28a 180 av_packet_unref(pkt);
6f3e0b21 181 return AVERROR(EIO);
d1e0d21f
MG
182 }
183
184 pkt->stream_index = thp->audio_stream_index;
5a9b9522
JR
185 if (thp->audiosize >= 8)
186 pkt->duration = AV_RB32(&pkt->data[4]);
187
d1e0d21f
MG
188 thp->audiosize = 0;
189 thp->frame++;
190 }
efb0c399
DB
191
192 return 0;
193}
194
c6610a21 195AVInputFormat ff_thp_demuxer = {
dfc2c4d9
AK
196 .name = "thp",
197 .long_name = NULL_IF_CONFIG_SMALL("THP"),
198 .priv_data_size = sizeof(ThpDemuxContext),
199 .read_probe = thp_probe,
200 .read_header = thp_read_header,
201 .read_packet = thp_read_packet
efb0c399 202};