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
{
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
vst->
codec
->
width
=
avio_rl32
(pb);
107
vst->
codec
->
height
=
avio_rl32
(pb);
108
avio_skip
(pb, 4);
109
vst->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
110
vst->
codec
->
codec_tag
= 0;
111
vst->
codec
->
codec_id
=
AV_CODEC_ID_PAF_VIDEO
;
112
avpriv_set_pts_info
(vst, 64, 1, 10);
113
114
ast =
avformat_new_stream
(s, 0);
115
if
(!ast)
116
return
AVERROR
(ENOMEM);
117
118
ast->
start_time
= 0;
119
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
120
ast->
codec
->
codec_tag
= 0;
121
ast->
codec
->
codec_id
=
AV_CODEC_ID_PAF_AUDIO
;
122
ast->
codec
->
channels
= 2;
123
ast->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
124
ast->
codec
->
sample_rate
= 22050;
125
avpriv_set_pts_info
(ast, 64, 1, 22050);
126
127
p->
buffer_size
=
avio_rl32
(pb);
128
p->
preload_count
=
avio_rl32
(pb);
129
p->
frame_blks
=
avio_rl32
(pb);
130
p->
start_offset
=
avio_rl32
(pb);
131
p->
max_video_blks
=
avio_rl32
(pb);
132
p->
max_audio_blks
=
avio_rl32
(pb);
133
if
(p->
buffer_size
< 175 ||
134
p->
max_audio_blks
< 2 ||
135
p->
max_video_blks
< 1 ||
136
p->
frame_blks
< 1 ||
137
p->
nb_frames
< 1 ||
138
p->
preload_count
< 1 ||
139
p->
buffer_size
> 2048 ||
140
p->
max_video_blks
> 2048 ||
141
p->
max_audio_blks
> 2048 ||
142
p->
nb_frames
> INT_MAX /
sizeof
(uint32_t) ||
143
p->
frame_blks
> INT_MAX /
sizeof
(uint32_t))
144
return
AVERROR_INVALIDDATA
;
145
146
p->
blocks_count_table
=
av_mallocz
(p->
nb_frames
*
sizeof
(uint32_t));
147
p->
frames_offset_table
=
av_mallocz
(p->
nb_frames
*
sizeof
(uint32_t));
148
p->
blocks_offset_table
=
av_mallocz
(p->
frame_blks
*
sizeof
(uint32_t));
149
150
p->
video_size
= p->
max_video_blks
* p->
buffer_size
;
151
p->
video_frame
=
av_mallocz
(p->
video_size
);
152
153
p->
audio_size
= p->
max_audio_blks
* p->
buffer_size
;
154
p->
audio_frame
=
av_mallocz
(p->
audio_size
);
155
p->
temp_audio_frame
=
av_mallocz
(p->
audio_size
);
156
157
if
(!p->
blocks_count_table
||
158
!p->
frames_offset_table
||
159
!p->
blocks_offset_table
||
160
!p->
video_frame
||
161
!p->
audio_frame
||
162
!p->
temp_audio_frame
) {
163
ret =
AVERROR
(ENOMEM);
164
goto
fail;
165
}
166
167
avio_seek
(pb, p->
buffer_size
, SEEK_SET);
168
169
read_table
(s, p->
blocks_count_table
, p->
nb_frames
);
170
read_table
(s, p->
frames_offset_table
, p->
nb_frames
);
171
read_table
(s, p->
blocks_offset_table
, p->
frame_blks
);
172
173
p->
got_audio
= 0;
174
p->
current_frame
= 0;
175
p->
current_frame_block
= 0;
176
177
avio_seek
(pb, p->
start_offset
, SEEK_SET);
178
179
return
0;
180
181
fail:
182
read_close
(s);
183
184
return
ret
;
185
}
186
187
static
int
read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
188
{
189
PAFDemuxContext
*p = s->
priv_data
;
190
AVIOContext
*pb = s->
pb
;
191
uint32_t
count
,
offset
;
192
int
size
, i;
193
194
if
(p->
current_frame
>= p->
nb_frames
)
195
return
AVERROR_EOF
;
196
197
if
(
url_feof
(pb))
198
return
AVERROR_EOF
;
199
200
if
(p->
got_audio
) {
201
if
(
av_new_packet
(pkt, p->
audio_size
) < 0)
202
return
AVERROR
(ENOMEM);
203
204
memcpy(pkt->
data
, p->
temp_audio_frame
, p->
audio_size
);
205
pkt->
duration
=
PAF_SOUND_SAMPLES
* (p->
audio_size
/
PAF_SOUND_FRAME_SIZE
);
206
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
207
pkt->
stream_index
= 1;
208
p->
got_audio
= 0;
209
return
pkt->
size
;
210
}
211
212
count = (p->
current_frame
== 0) ? p->
preload_count
: p->
blocks_count_table
[p->
current_frame
- 1];
213
for
(i = 0; i <
count
; i++) {
214
if
(p->
current_frame_block
>= p->
frame_blks
)
215
return
AVERROR_INVALIDDATA
;
216
217
offset = p->
blocks_offset_table
[p->
current_frame_block
] & ~(1
U
<< 31);
218
if
(p->
blocks_offset_table
[p->
current_frame_block
] & (1
U
<< 31)) {
219
if
(offset > p->
audio_size
- p->
buffer_size
)
220
return
AVERROR_INVALIDDATA
;
221
222
avio_read
(pb, p->
audio_frame
+ offset, p->
buffer_size
);
223
if
(offset == (p->
max_audio_blks
- 2) * p->
buffer_size
) {
224
memcpy(p->
temp_audio_frame
, p->
audio_frame
, p->
audio_size
);
225
p->
got_audio
= 1;
226
}
227
}
else
{
228
if
(offset > p->
video_size
- p->
buffer_size
)
229
return
AVERROR_INVALIDDATA
;
230
231
avio_read
(pb, p->
video_frame
+ offset, p->
buffer_size
);
232
}
233
p->
current_frame_block
++;
234
}
235
236
size = p->
video_size
- p->
frames_offset_table
[p->
current_frame
];
237
if
(size < 1)
238
return
AVERROR_INVALIDDATA
;
239
240
if
(
av_new_packet
(pkt, size) < 0)
241
return
AVERROR
(ENOMEM);
242
243
pkt->
stream_index
= 0;
244
pkt->
duration
= 1;
245
memcpy(pkt->
data
, p->
video_frame
+ p->
frames_offset_table
[p->
current_frame
], size);
246
if
(pkt->
data
[0] & 0x20)
247
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
248
p->
current_frame
++;
249
250
return
pkt->
size
;
251
}
252
253
AVInputFormat
ff_paf_demuxer
= {
254
.
name
=
"paf"
,
255
.long_name =
NULL_IF_CONFIG_SMALL
(
"Amazing Studio Packed Animation File"
),
256
.priv_data_size =
sizeof
(
PAFDemuxContext
),
257
.
read_probe
=
read_probe
,
258
.
read_header
=
read_header
,
259
.
read_packet
=
read_packet
,
260
.
read_close
=
read_close
,
261
};
Generated on Wed Jul 10 2013 23:48:03 for FFmpeg by
1.8.2