FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
tiertexseq.c
Go to the documentation of this file.
1
/*
2
* Tiertex Limited SEQ File Demuxer
3
* Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
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
/**
23
* @file
24
* Tiertex Limited SEQ file demuxer
25
*/
26
27
#include "
libavutil/channel_layout.h
"
28
#include "
avformat.h
"
29
#include "
internal.h
"
30
31
#define SEQ_FRAME_SIZE 6144
32
#define SEQ_FRAME_W 256
33
#define SEQ_FRAME_H 128
34
#define SEQ_NUM_FRAME_BUFFERS 30
35
#define SEQ_AUDIO_BUFFER_SIZE 882
36
#define SEQ_SAMPLE_RATE 22050
37
#define SEQ_FRAME_RATE 25
38
39
40
typedef
struct
TiertexSeqFrameBuffer
{
41
int
fill_size
;
42
int
data_size
;
43
unsigned
char
*
data
;
44
}
TiertexSeqFrameBuffer
;
45
46
typedef
struct
SeqDemuxContext
{
47
int
audio_stream_index
;
48
int
video_stream_index
;
49
int
current_frame_pts
;
50
int
current_frame_offs
;
51
TiertexSeqFrameBuffer
frame_buffers
[
SEQ_NUM_FRAME_BUFFERS
];
52
int
frame_buffers_count
;
53
unsigned
int
current_audio_data_size
;
54
unsigned
int
current_audio_data_offs
;
55
unsigned
int
current_pal_data_size
;
56
unsigned
int
current_pal_data_offs
;
57
unsigned
int
current_video_data_size
;
58
unsigned
char
*
current_video_data_ptr
;
59
int
audio_buffer_full
;
60
}
SeqDemuxContext
;
61
62
63
static
int
seq_probe
(
AVProbeData
*p)
64
{
65
int
i;
66
67
if
(p->
buf_size
< 258)
68
return
0;
69
70
/* there's no real header in a .seq file, the only thing they have in common */
71
/* is the first 256 bytes of the file which are always filled with 0 */
72
for
(i = 0; i < 256; i++)
73
if
(p->
buf
[i])
74
return
0;
75
76
if
(p->
buf
[256]==0 && p->
buf
[257]==0)
77
return
0;
78
79
/* only one fourth of the score since the previous check is too naive */
80
return
AVPROBE_SCORE_MAX
/ 4;
81
}
82
83
static
int
seq_init_frame_buffers
(
SeqDemuxContext
*seq,
AVIOContext
*pb)
84
{
85
int
i, sz;
86
TiertexSeqFrameBuffer
*seq_buffer;
87
88
avio_seek
(pb, 256, SEEK_SET);
89
90
for
(i = 0; i <
SEQ_NUM_FRAME_BUFFERS
; i++) {
91
sz =
avio_rl16
(pb);
92
if
(sz == 0)
93
break
;
94
else
{
95
seq_buffer = &seq->
frame_buffers
[i];
96
seq_buffer->
fill_size
= 0;
97
seq_buffer->
data_size
= sz;
98
seq_buffer->
data
=
av_malloc
(sz);
99
if
(!seq_buffer->
data
)
100
return
AVERROR
(ENOMEM);
101
}
102
}
103
seq->
frame_buffers_count
= i;
104
return
0;
105
}
106
107
static
int
seq_fill_buffer
(
SeqDemuxContext
*seq,
AVIOContext
*pb,
int
buffer_num,
unsigned
int
data_offs,
int
data_size)
108
{
109
TiertexSeqFrameBuffer
*seq_buffer;
110
111
if
(buffer_num >=
SEQ_NUM_FRAME_BUFFERS
)
112
return
AVERROR_INVALIDDATA
;
113
114
seq_buffer = &seq->
frame_buffers
[buffer_num];
115
if
(seq_buffer->
fill_size
+ data_size > seq_buffer->
data_size
|| data_size <= 0)
116
return
AVERROR_INVALIDDATA
;
117
118
avio_seek
(pb, seq->
current_frame_offs
+ data_offs, SEEK_SET);
119
if
(
avio_read
(pb, seq_buffer->
data
+ seq_buffer->
fill_size
, data_size) != data_size)
120
return
AVERROR
(EIO);
121
122
seq_buffer->
fill_size
+= data_size;
123
return
0;
124
}
125
126
static
int
seq_parse_frame_data
(
SeqDemuxContext
*seq,
AVIOContext
*pb)
127
{
128
unsigned
int
offset_table
[4], buffer_num[4];
129
TiertexSeqFrameBuffer
*seq_buffer;
130
int
i, e, err;
131
132
seq->
current_frame_offs
+=
SEQ_FRAME_SIZE
;
133
avio_seek
(pb, seq->
current_frame_offs
, SEEK_SET);
134
135
/* sound data */
136
seq->
current_audio_data_offs
=
avio_rl16
(pb);
137
if
(seq->
current_audio_data_offs
) {
138
seq->
current_audio_data_size
=
SEQ_AUDIO_BUFFER_SIZE
* 2;
139
}
else
{
140
seq->
current_audio_data_size
= 0;
141
}
142
143
/* palette data */
144
seq->
current_pal_data_offs
=
avio_rl16
(pb);
145
if
(seq->
current_pal_data_offs
) {
146
seq->
current_pal_data_size
= 768;
147
}
else
{
148
seq->
current_pal_data_size
= 0;
149
}
150
151
/* video data */
152
for
(i = 0; i < 4; i++)
153
buffer_num[i] =
avio_r8
(pb);
154
155
for
(i = 0; i < 4; i++)
156
offset_table[i] =
avio_rl16
(pb);
157
158
for
(i = 0; i < 3; i++) {
159
if
(offset_table[i]) {
160
for
(e = i + 1; e < 3 && offset_table[e] == 0; e++);
161
err =
seq_fill_buffer
(seq, pb, buffer_num[1 + i],
162
offset_table[i],
163
offset_table[e] - offset_table[i]);
164
if
(err)
165
return
err;
166
}
167
}
168
169
if
(buffer_num[0] != 255) {
170
if
(buffer_num[0] >=
SEQ_NUM_FRAME_BUFFERS
)
171
return
AVERROR_INVALIDDATA
;
172
173
seq_buffer = &seq->
frame_buffers
[buffer_num[0]];
174
seq->
current_video_data_size
= seq_buffer->
fill_size
;
175
seq->
current_video_data_ptr
= seq_buffer->
data
;
176
seq_buffer->
fill_size
= 0;
177
}
else
{
178
seq->
current_video_data_size
= 0;
179
seq->
current_video_data_ptr
= 0;
180
}
181
182
return
0;
183
}
184
185
static
int
seq_read_header
(
AVFormatContext
*
s
)
186
{
187
int
i, rc;
188
SeqDemuxContext
*seq = s->
priv_data
;
189
AVIOContext
*pb = s->
pb
;
190
AVStream
*st;
191
192
/* init internal buffers */
193
rc =
seq_init_frame_buffers
(seq, pb);
194
if
(rc)
195
return
rc;
196
197
seq->
current_frame_offs
= 0;
198
199
/* preload (no audio data, just buffer operations related data) */
200
for
(i = 1; i <= 100; i++) {
201
rc =
seq_parse_frame_data
(seq, pb);
202
if
(rc)
203
return
rc;
204
}
205
206
seq->
current_frame_pts
= 0;
207
208
seq->
audio_buffer_full
= 0;
209
210
/* initialize the video decoder stream */
211
st =
avformat_new_stream
(s, NULL);
212
if
(!st)
213
return
AVERROR
(ENOMEM);
214
215
avpriv_set_pts_info
(st, 32, 1,
SEQ_FRAME_RATE
);
216
seq->
video_stream_index
= st->
index
;
217
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
218
st->
codec
->
codec_id
=
AV_CODEC_ID_TIERTEXSEQVIDEO
;
219
st->
codec
->
codec_tag
= 0;
/* no fourcc */
220
st->
codec
->
width
=
SEQ_FRAME_W
;
221
st->
codec
->
height
=
SEQ_FRAME_H
;
222
223
/* initialize the audio decoder stream */
224
st =
avformat_new_stream
(s, NULL);
225
if
(!st)
226
return
AVERROR
(ENOMEM);
227
228
st->
start_time
= 0;
229
avpriv_set_pts_info
(st, 32, 1,
SEQ_SAMPLE_RATE
);
230
seq->
audio_stream_index
= st->
index
;
231
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
232
st->
codec
->
codec_id
=
AV_CODEC_ID_PCM_S16BE
;
233
st->
codec
->
codec_tag
= 0;
/* no tag */
234
st->
codec
->
channels
= 1;
235
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
236
st->
codec
->
sample_rate
=
SEQ_SAMPLE_RATE
;
237
st->
codec
->
bits_per_coded_sample
= 16;
238
st->
codec
->
bit_rate
= st->
codec
->
sample_rate
* st->
codec
->
bits_per_coded_sample
* st->
codec
->
channels
;
239
st->
codec
->
block_align
= st->
codec
->
channels
* st->
codec
->
bits_per_coded_sample
/ 8;
240
241
return
0;
242
}
243
244
static
int
seq_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
245
{
246
int
rc;
247
SeqDemuxContext
*seq = s->
priv_data
;
248
AVIOContext
*pb = s->
pb
;
249
250
if
(!seq->
audio_buffer_full
) {
251
rc =
seq_parse_frame_data
(seq, pb);
252
if
(rc)
253
return
rc;
254
255
/* video packet */
256
if
(seq->
current_pal_data_size
+ seq->
current_video_data_size
!= 0) {
257
if
(
av_new_packet
(pkt, 1 + seq->
current_pal_data_size
+ seq->
current_video_data_size
))
258
return
AVERROR
(ENOMEM);
259
260
pkt->
data
[0] = 0;
261
if
(seq->
current_pal_data_size
) {
262
pkt->
data
[0] |= 1;
263
avio_seek
(pb, seq->
current_frame_offs
+ seq->
current_pal_data_offs
, SEEK_SET);
264
if
(
avio_read
(pb, &pkt->
data
[1], seq->
current_pal_data_size
) != seq->
current_pal_data_size
)
265
return
AVERROR
(EIO);
266
}
267
if
(seq->
current_video_data_size
) {
268
pkt->
data
[0] |= 2;
269
memcpy(&pkt->
data
[1 + seq->
current_pal_data_size
],
270
seq->
current_video_data_ptr
,
271
seq->
current_video_data_size
);
272
}
273
pkt->
stream_index
= seq->
video_stream_index
;
274
pkt->
pts
= seq->
current_frame_pts
;
275
276
/* sound buffer will be processed on next read_packet() call */
277
seq->
audio_buffer_full
= 1;
278
return
0;
279
}
280
}
281
282
/* audio packet */
283
if
(seq->
current_audio_data_offs
== 0)
/* end of data reached */
284
return
AVERROR
(EIO);
285
286
avio_seek
(pb, seq->
current_frame_offs
+ seq->
current_audio_data_offs
, SEEK_SET);
287
rc =
av_get_packet
(pb, pkt, seq->
current_audio_data_size
);
288
if
(rc < 0)
289
return
rc;
290
291
pkt->
stream_index
= seq->
audio_stream_index
;
292
seq->
current_frame_pts
++;
293
294
seq->
audio_buffer_full
= 0;
295
return
0;
296
}
297
298
static
int
seq_read_close
(
AVFormatContext
*
s
)
299
{
300
int
i;
301
SeqDemuxContext
*seq = s->
priv_data
;
302
303
for
(i = 0; i <
SEQ_NUM_FRAME_BUFFERS
; i++)
304
av_free
(seq->
frame_buffers
[i].
data
);
305
306
return
0;
307
}
308
309
AVInputFormat
ff_tiertexseq_demuxer
= {
310
.
name
=
"tiertexseq"
,
311
.long_name =
NULL_IF_CONFIG_SMALL
(
"Tiertex Limited SEQ"
),
312
.priv_data_size =
sizeof
(
SeqDemuxContext
),
313
.
read_probe
=
seq_probe
,
314
.
read_header
=
seq_read_header
,
315
.
read_packet
=
seq_read_packet
,
316
.
read_close
=
seq_read_close
,
317
};
Generated on Sat Jan 25 2014 19:52:05 for FFmpeg by
1.8.2