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
paf.c
Go to the documentation of this file.
1
/*
2
* Packed Animation File demuxer
3
* Copyright (c) 2012 Paul B Mahol
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
#include "
libavutil/channel_layout.h
"
23
#include "
libavcodec/paf.h
"
24
#include "
avformat.h
"
25
#include "
internal.h
"
26
27
#define MAGIC "Packed Animation File V1.0\n(c) 1992-96 Amazing Studio\x0a\x1a"
28
29
typedef
struct
PAFDemuxContext
{
30
uint32_t
buffer_size
;
31
uint32_t
frame_blks
;
32
uint32_t
nb_frames
;
33
uint32_t
start_offset
;
34
uint32_t
preload_count
;
35
uint32_t
max_video_blks
;
36
uint32_t
max_audio_blks
;
37
38
uint32_t
current_frame
;
39
uint32_t
current_frame_count
;
40
uint32_t
current_frame_block
;
41
42
uint32_t *
blocks_count_table
;
43
uint32_t *
frames_offset_table
;
44
uint32_t *
blocks_offset_table
;
45
46
uint8_t
*
video_frame
;
47
int
video_size
;
48
49
uint8_t
*
audio_frame
;
50
uint8_t
*
temp_audio_frame
;
51
int
audio_size
;
52
53
int
got_audio
;
54
}
PAFDemuxContext
;
55
56
static
int
read_probe
(
AVProbeData
*p)
57
{
58
if
((p->
buf_size
>= strlen(
MAGIC
)) &&
59
!memcmp(p->
buf
,
MAGIC
, strlen(
MAGIC
)))
60
return
AVPROBE_SCORE_MAX
;
61
return
0;
62
}
63
64
static
int
read_close
(
AVFormatContext
*
s
)
65
{
66
PAFDemuxContext
*p = s->
priv_data
;
67
68
av_freep
(&p->
blocks_count_table
);
69
av_freep
(&p->
frames_offset_table
);
70
av_freep
(&p->
blocks_offset_table
);
71
av_freep
(&p->
video_frame
);
72
av_freep
(&p->
audio_frame
);
73
av_freep
(&p->
temp_audio_frame
);
74
75
return
0;
76
}
77
78
static
void
read_table
(
AVFormatContext
*
s
, uint32_t *
table
, uint32_t
count
)
79
{
80
int
i;
81
82
for
(i = 0; i <
count
; i++)
83
table[i] =
avio_rl32
(s->
pb
);
84
85
avio_skip
(s->
pb
, 4 * (
FFALIGN
(count, 512) - count));
86
}
87
88
static
int
read_header
(
AVFormatContext
*
s
)
89
{
90
PAFDemuxContext
*p = s->
priv_data
;
91
AVIOContext
*pb = s->
pb
;
92
AVStream
*ast, *vst;
93
int
ret
= 0;
94
95
avio_skip
(pb, 132);
96
97
vst =
avformat_new_stream
(s, 0);
98
if
(!vst)
99
return
AVERROR
(ENOMEM);
100
101
vst->
start_time
= 0;
102
vst->
nb_frames
=
103
vst->
duration
=
104
p->
nb_frames
=
avio_rl32
(pb);
105
avio_skip
(pb, 4);
106
107
vst->
codec
->
width
=
avio_rl32
(pb);
108
vst->
codec
->
height
=
avio_rl32
(pb);
109
avio_skip
(pb, 4);
110
111
vst->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
112
vst->
codec
->
codec_tag
= 0;
113
vst->
codec
->
codec_id
=
AV_CODEC_ID_PAF_VIDEO
;
114
avpriv_set_pts_info
(vst, 64, 1, 10);
115
116
ast =
avformat_new_stream
(s, 0);
117
if
(!ast)
118
return
AVERROR
(ENOMEM);
119
120
ast->
start_time
= 0;
121
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
122
ast->
codec
->
codec_tag
= 0;
123
ast->
codec
->
codec_id
=
AV_CODEC_ID_PAF_AUDIO
;
124
ast->
codec
->
channels
= 2;
125
ast->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
126
ast->
codec
->
sample_rate
= 22050;
127
avpriv_set_pts_info
(ast, 64, 1, 22050);
128
129
p->
buffer_size
=
avio_rl32
(pb);
130
p->
preload_count
=
avio_rl32
(pb);
131
p->
frame_blks
=
avio_rl32
(pb);
132
p->
start_offset
=
avio_rl32
(pb);
133
p->
max_video_blks
=
avio_rl32
(pb);
134
p->
max_audio_blks
=
avio_rl32
(pb);
135
if
(p->
buffer_size
< 175 ||
136
p->
max_audio_blks
< 2 ||
137
p->
max_video_blks
< 1 ||
138
p->
frame_blks
< 1 ||
139
p->
nb_frames
< 1 ||
140
p->
preload_count
< 1 ||
141
p->
buffer_size
> 2048 ||
142
p->
max_video_blks
> 2048 ||
143
p->
max_audio_blks
> 2048 ||
144
p->
nb_frames
> INT_MAX /
sizeof
(uint32_t) ||
145
p->
frame_blks
> INT_MAX /
sizeof
(uint32_t))
146
return
AVERROR_INVALIDDATA
;
147
148
p->
blocks_count_table
=
av_mallocz
(p->
nb_frames
*
149
sizeof
(*p->
blocks_count_table
));
150
p->
frames_offset_table
=
av_mallocz
(p->
nb_frames
*
151
sizeof
(*p->
frames_offset_table
));
152
p->
blocks_offset_table
=
av_mallocz
(p->
frame_blks
*
153
sizeof
(*p->
blocks_offset_table
));
154
155
p->
video_size
= p->
max_video_blks
* p->
buffer_size
;
156
p->
video_frame
=
av_mallocz
(p->
video_size
);
157
158
p->
audio_size
= p->
max_audio_blks
* p->
buffer_size
;
159
p->
audio_frame
=
av_mallocz
(p->
audio_size
);
160
p->
temp_audio_frame
=
av_mallocz
(p->
audio_size
);
161
162
if
(!p->
blocks_count_table
||
163
!p->
frames_offset_table
||
164
!p->
blocks_offset_table
||
165
!p->
video_frame
||
166
!p->
audio_frame
||
167
!p->
temp_audio_frame
) {
168
ret =
AVERROR
(ENOMEM);
169
goto
fail;
170
}
171
172
avio_seek
(pb, p->
buffer_size
, SEEK_SET);
173
174
read_table
(s, p->
blocks_count_table
, p->
nb_frames
);
175
read_table
(s, p->
frames_offset_table
, p->
nb_frames
);
176
read_table
(s, p->
blocks_offset_table
, p->
frame_blks
);
177
178
p->
got_audio
= 0;
179
p->
current_frame
= 0;
180
p->
current_frame_block
= 0;
181
182
avio_seek
(pb, p->
start_offset
, SEEK_SET);
183
184
return
0;
185
186
fail:
187
read_close
(s);
188
189
return
ret
;
190
}
191
192
static
int
read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
193
{
194
PAFDemuxContext
*p = s->
priv_data
;
195
AVIOContext
*pb = s->
pb
;
196
uint32_t
count
,
offset
;
197
int
size
, i;
198
199
if
(p->
current_frame
>= p->
nb_frames
)
200
return
AVERROR_EOF
;
201
202
if
(
avio_feof
(pb))
203
return
AVERROR_EOF
;
204
205
if
(p->
got_audio
) {
206
if
(
av_new_packet
(pkt, p->
audio_size
) < 0)
207
return
AVERROR
(ENOMEM);
208
209
memcpy(pkt->
data
, p->
temp_audio_frame
, p->
audio_size
);
210
pkt->
duration
=
PAF_SOUND_SAMPLES
* (p->
audio_size
/
PAF_SOUND_FRAME_SIZE
);
211
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
212
pkt->
stream_index
= 1;
213
p->
got_audio
= 0;
214
return
pkt->
size
;
215
}
216
217
count = (p->
current_frame
== 0) ? p->
preload_count
218
: p->
blocks_count_table
[p->
current_frame
- 1];
219
for
(i = 0; i <
count
; i++) {
220
if
(p->
current_frame_block
>= p->
frame_blks
)
221
return
AVERROR_INVALIDDATA
;
222
223
offset = p->
blocks_offset_table
[p->
current_frame_block
] & ~(1
U
<< 31);
224
if
(p->
blocks_offset_table
[p->
current_frame_block
] & (1
U
<< 31)) {
225
if
(offset > p->
audio_size
- p->
buffer_size
)
226
return
AVERROR_INVALIDDATA
;
227
228
avio_read
(pb, p->
audio_frame
+ offset, p->
buffer_size
);
229
if
(offset == (p->
max_audio_blks
- 2) * p->
buffer_size
) {
230
memcpy(p->
temp_audio_frame
, p->
audio_frame
, p->
audio_size
);
231
p->
got_audio
= 1;
232
}
233
}
else
{
234
if
(offset > p->
video_size
- p->
buffer_size
)
235
return
AVERROR_INVALIDDATA
;
236
237
avio_read
(pb, p->
video_frame
+ offset, p->
buffer_size
);
238
}
239
p->
current_frame_block
++;
240
}
241
242
if
(p->
frames_offset_table
[p->
current_frame
] >= p->
video_size
)
243
return
AVERROR_INVALIDDATA
;
244
245
size = p->
video_size
- p->
frames_offset_table
[p->
current_frame
];
246
247
if
(
av_new_packet
(pkt, size) < 0)
248
return
AVERROR
(ENOMEM);
249
250
pkt->
stream_index
= 0;
251
pkt->
duration
= 1;
252
memcpy(pkt->
data
, p->
video_frame
+ p->
frames_offset_table
[p->
current_frame
], size);
253
if
(pkt->
data
[0] & 0x20)
254
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
255
p->
current_frame
++;
256
257
return
pkt->
size
;
258
}
259
260
AVInputFormat
ff_paf_demuxer
= {
261
.
name
=
"paf"
,
262
.long_name =
NULL_IF_CONFIG_SMALL
(
"Amazing Studio Packed Animation File"
),
263
.priv_data_size =
sizeof
(
PAFDemuxContext
),
264
.
read_probe
=
read_probe
,
265
.
read_header
=
read_header
,
266
.
read_packet
=
read_packet
,
267
.
read_close
=
read_close
,
268
};
Generated on Sun Mar 8 2015 02:35:11 for FFmpeg by
1.8.2