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
if
(p->
frames_offset_table
[p->
current_frame
] >= p->
video_size
)
237
return
AVERROR_INVALIDDATA
;
238
239
size = p->
video_size
- p->
frames_offset_table
[p->
current_frame
];
240
241
if
(
av_new_packet
(pkt, size) < 0)
242
return
AVERROR
(ENOMEM);
243
244
pkt->
stream_index
= 0;
245
pkt->
duration
= 1;
246
memcpy(pkt->
data
, p->
video_frame
+ p->
frames_offset_table
[p->
current_frame
], size);
247
if
(pkt->
data
[0] & 0x20)
248
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
249
p->
current_frame
++;
250
251
return
pkt->
size
;
252
}
253
254
AVInputFormat
ff_paf_demuxer
= {
255
.
name
=
"paf"
,
256
.long_name =
NULL_IF_CONFIG_SMALL
(
"Amazing Studio Packed Animation File"
),
257
.priv_data_size =
sizeof
(
PAFDemuxContext
),
258
.
read_probe
=
read_probe
,
259
.
read_header
=
read_header
,
260
.
read_packet
=
read_packet
,
261
.
read_close
=
read_close
,
262
};
Generated on Sat Jan 25 2014 19:51:53 for FFmpeg by
1.8.2