FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
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
av_log_ask_for_sample
(s,
"max_pages != "
AV_STRINGIFY
(
MAX_PAGES
)
"\n"
);
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
anm->
record
= -1;
162
return
0;
163
164
invalid:
165
av_log_ask_for_sample
(s,
NULL
);
166
return
AVERROR_PATCHWELCOME
;
167
}
168
169
static
int
read_packet
(
AVFormatContext
*s,
170
AVPacket
*
pkt
)
171
{
172
AnmDemuxContext
*anm = s->
priv_data
;
173
AVIOContext
*pb = s->
pb
;
174
Page
*p;
175
int
tmp, record_size;
176
177
if
(
url_feof
(s->
pb
))
178
return
AVERROR
(EIO);
179
180
if
(anm->
page
< 0)
181
return
anm->
page
;
182
183
repeat:
184
p = &anm->
pt
[anm->
page
];
185
186
/* parse page header */
187
if
(anm->
record
< 0) {
188
avio_seek
(pb, anm->
page_table_offset
+
MAX_PAGES
*6 + (anm->
page
<<16), SEEK_SET);
189
avio_skip
(pb, 8 + 2*p->
nb_records
);
190
anm->
record
= 0;
191
}
192
193
/* if we have fetched all records in this page, then find the
194
next page and repeat */
195
if
(anm->
record
>= p->
nb_records
) {
196
anm->
page
=
find_record
(anm, p->
base_record
+ p->
nb_records
);
197
if
(anm->
page
< 0)
198
return
anm->
page
;
199
anm->
record
= -1;
200
goto
repeat;
201
}
202
203
/* fetch record size */
204
tmp =
avio_tell
(pb);
205
avio_seek
(pb, anm->
page_table_offset
+
MAX_PAGES
*6 + (anm->
page
<<16) +
206
8 + anm->
record
* 2, SEEK_SET);
207
record_size =
avio_rl16
(pb);
208
avio_seek
(pb, tmp, SEEK_SET);
209
210
/* fetch record */
211
pkt->
size
=
av_get_packet
(s->
pb
, pkt, record_size);
212
if
(pkt->
size
< 0)
213
return
pkt->
size
;
214
if
(p->
base_record
+ anm->
record
== 0)
215
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
216
217
anm->
record
++;
218
return
0;
219
}
220
221
AVInputFormat
ff_anm_demuxer
= {
222
.
name
=
"anm"
,
223
.long_name =
NULL_IF_CONFIG_SMALL
(
"Deluxe Paint Animation"
),
224
.priv_data_size =
sizeof
(
AnmDemuxContext
),
225
.
read_probe
=
probe
,
226
.
read_header
=
read_header
,
227
.
read_packet
=
read_packet
,
228
};
Generated on Sat May 25 2013 04:01:01 for FFmpeg by
1.8.2