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
anm.c
Go to the documentation of this file.
1
/*
2
* Deluxe Paint Animation demuxer
3
* Copyright (c) 2009 Peter Ross
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
* Deluxe Paint Animation demuxer
25
*/
26
27
#include "
libavutil/intreadwrite.h
"
28
#include "
avformat.h
"
29
#include "
internal.h
"
30
31
typedef
struct
{
32
int
base_record
;
33
unsigned
int
nb_records
;
34
int
size
;
35
}
Page
;
36
37
typedef
struct
{
38
unsigned
int
nb_pages
;
/**< total pages in file */
39
unsigned
int
nb_records
;
/**< total records in file */
40
int
page_table_offset
;
41
#define MAX_PAGES 256
/**< Deluxe Paint hardcoded value */
42
Page
pt
[
MAX_PAGES
];
/**< page table */
43
int
page
;
/**< current page (or AVERROR_xxx code) */
44
int
record
;
/**< current record (with in page) */
45
}
AnmDemuxContext
;
46
47
#define LPF_TAG MKTAG('L','P','F',' ')
48
#define ANIM_TAG MKTAG('A','N','I','M')
49
50
static
int
probe
(
AVProbeData
*p)
51
{
52
/* verify tags and video dimensions */
53
if
(
AV_RL32
(&p->
buf
[0]) ==
LPF_TAG
&&
54
AV_RL32
(&p->
buf
[16]) ==
ANIM_TAG
&&
55
AV_RL16
(&p->
buf
[20]) &&
AV_RL16
(&p->
buf
[22]))
56
return
AVPROBE_SCORE_MAX
;
57
return
0;
58
}
59
60
/**
61
* @return page containing the requested record or AVERROR_XXX
62
*/
63
static
int
find_record
(
const
AnmDemuxContext
*anm,
int
record)
64
{
65
int
i;
66
67
if
(record >= anm->
nb_records
)
68
return
AVERROR_EOF
;
69
70
for
(i = 0; i <
MAX_PAGES
; i++) {
71
const
Page
*p = &anm->
pt
[i];
72
if
(p->
nb_records
> 0 && record >= p->
base_record
&& record < p->base_record + p->
nb_records
)
73
return
i;
74
}
75
76
return
AVERROR_INVALIDDATA
;
77
}
78
79
static
int
read_header
(
AVFormatContext
*
s
)
80
{
81
AnmDemuxContext
*anm = s->
priv_data
;
82
AVIOContext
*pb = s->
pb
;
83
AVStream
*st;
84
int
i,
ret
;
85
86
avio_skip
(pb, 4);
/* magic number */
87
if
(
avio_rl16
(pb) !=
MAX_PAGES
) {
88
avpriv_request_sample
(s,
"max_pages != "
AV_STRINGIFY
(
MAX_PAGES
));
89
return
AVERROR_PATCHWELCOME
;
90
}
91
92
anm->
nb_pages
=
avio_rl16
(pb);
93
anm->
nb_records
=
avio_rl32
(pb);
94
avio_skip
(pb, 2);
/* max records per page */
95
anm->
page_table_offset
=
avio_rl16
(pb);
96
if
(
avio_rl32
(pb) !=
ANIM_TAG
)
97
return
AVERROR_INVALIDDATA
;
98
99
/* video stream */
100
st =
avformat_new_stream
(s, NULL);
101
if
(!st)
102
return
AVERROR
(ENOMEM);
103
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
104
st->
codec
->
codec_id
=
AV_CODEC_ID_ANM
;
105
st->
codec
->
codec_tag
= 0;
/* no fourcc */
106
st->
codec
->
width
=
avio_rl16
(pb);
107
st->
codec
->
height
=
avio_rl16
(pb);
108
if
(
avio_r8
(pb) != 0)
109
goto
invalid;
110
avio_skip
(pb, 1);
/* frame rate multiplier info */
111
112
/* ignore last delta record (used for looping) */
113
if
(
avio_r8
(pb))
/* has_last_delta */
114
anm->
nb_records
=
FFMAX
(anm->
nb_records
- 1, 0);
115
116
avio_skip
(pb, 1);
/* last_delta_valid */
117
118
if
(
avio_r8
(pb) != 0)
119
goto
invalid;
120
121
if
(
avio_r8
(pb) != 1)
122
goto
invalid;
123
124
avio_skip
(pb, 1);
/* other recs per frame */
125
126
if
(
avio_r8
(pb) != 1)
127
goto
invalid;
128
129
avio_skip
(pb, 32);
/* record_types */
130
st->
nb_frames
=
avio_rl32
(pb);
131
avpriv_set_pts_info
(st, 64, 1,
avio_rl16
(pb));
132
avio_skip
(pb, 58);
133
134
/* color cycling and palette data */
135
st->
codec
->
extradata_size
= 16*8 + 4*256;
136
st->
codec
->
extradata
=
av_mallocz
(st->
codec
->
extradata_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
137
if
(!st->
codec
->
extradata
) {
138
return
AVERROR
(ENOMEM);
139
}
140
ret =
avio_read
(pb, st->
codec
->
extradata
, st->
codec
->
extradata_size
);
141
if
(ret < 0)
142
return
ret
;
143
144
/* read page table */
145
ret =
avio_seek
(pb, anm->
page_table_offset
, SEEK_SET);
146
if
(ret < 0)
147
return
ret
;
148
149
for
(i = 0; i <
MAX_PAGES
; i++) {
150
Page
*p = &anm->
pt
[i];
151
p->
base_record
=
avio_rl16
(pb);
152
p->
nb_records
=
avio_rl16
(pb);
153
p->
size
=
avio_rl16
(pb);
154
}
155
156
/* find page of first frame */
157
anm->
page
=
find_record
(anm, 0);
158
if
(anm->
page
< 0) {
159
return
anm->
page
;
160
}
161
162
anm->
record
= -1;
163
return
0;
164
165
invalid:
166
avpriv_request_sample
(s,
"Invalid header element"
);
167
return
AVERROR_PATCHWELCOME
;
168
}
169
170
static
int
read_packet
(
AVFormatContext
*
s
,
171
AVPacket
*
pkt
)
172
{
173
AnmDemuxContext
*anm = s->
priv_data
;
174
AVIOContext
*pb = s->
pb
;
175
Page
*p;
176
int
tmp, record_size;
177
178
if
(
url_feof
(s->
pb
))
179
return
AVERROR
(EIO);
180
181
if
(anm->
page
< 0)
182
return
anm->
page
;
183
184
repeat:
185
p = &anm->
pt
[anm->
page
];
186
187
/* parse page header */
188
if
(anm->
record
< 0) {
189
avio_seek
(pb, anm->
page_table_offset
+
MAX_PAGES
*6 + (anm->
page
<<16), SEEK_SET);
190
avio_skip
(pb, 8 + 2*p->
nb_records
);
191
anm->
record
= 0;
192
}
193
194
/* if we have fetched all records in this page, then find the
195
next page and repeat */
196
if
(anm->
record
>= p->
nb_records
) {
197
anm->
page
=
find_record
(anm, p->
base_record
+ p->
nb_records
);
198
if
(anm->
page
< 0)
199
return
anm->
page
;
200
anm->
record
= -1;
201
goto
repeat;
202
}
203
204
/* fetch record size */
205
tmp =
avio_tell
(pb);
206
avio_seek
(pb, anm->
page_table_offset
+
MAX_PAGES
*6 + (anm->
page
<<16) +
207
8 + anm->
record
* 2, SEEK_SET);
208
record_size =
avio_rl16
(pb);
209
avio_seek
(pb, tmp, SEEK_SET);
210
211
/* fetch record */
212
pkt->
size
=
av_get_packet
(s->
pb
, pkt, record_size);
213
if
(pkt->
size
< 0)
214
return
pkt->
size
;
215
if
(p->
base_record
+ anm->
record
== 0)
216
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
217
218
anm->
record
++;
219
return
0;
220
}
221
222
AVInputFormat
ff_anm_demuxer
= {
223
.
name
=
"anm"
,
224
.long_name =
NULL_IF_CONFIG_SMALL
(
"Deluxe Paint Animation"
),
225
.priv_data_size =
sizeof
(
AnmDemuxContext
),
226
.
read_probe
=
probe
,
227
.
read_header
=
read_header
,
228
.
read_packet
=
read_packet
,
229
};
Generated on Sun Mar 23 2014 23:49:51 for FFmpeg by
1.8.2