2 * Deluxe Paint Animation demuxer
3 * Copyright (c) 2009 Peter Ross
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * Deluxe Paint Animation demuxer
27 #include "libavutil/intreadwrite.h"
33 unsigned int nb_records
;
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) */
47 #define LPF_TAG MKTAG('L','P','F',' ')
48 #define ANIM_TAG MKTAG('A','N','I','M')
50 static int probe(AVProbeData
*p
)
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
;
61 * @return page containing the requested record or AVERROR_XXX
63 static int find_record(const AnmDemuxContext
*anm
, int record
)
67 if (record
>= anm
->nb_records
)
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
)
76 return AVERROR_INVALIDDATA
;
79 static int read_header(AVFormatContext
*s
)
81 AnmDemuxContext
*anm
= s
->priv_data
;
82 AVIOContext
*pb
= s
->pb
;
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
;
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
;
100 st
= avformat_new_stream(s
, NULL
);
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)
110 avio_skip(pb
, 1); /* frame rate multiplier info */
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);
116 avio_skip(pb
, 1); /* last_delta_valid */
118 if (avio_r8(pb
) != 0)
121 if (avio_r8(pb
) != 1)
124 avio_skip(pb
, 1); /* other recs per frame */
126 if (avio_r8(pb
) != 1)
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
));
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 ret
= AVERROR(ENOMEM
);
141 ret
= avio_read(pb
, st
->codec
->extradata
, st
->codec
->extradata_size
);
145 /* read page table */
146 ret
= avio_seek(pb
, anm
->page_table_offset
, SEEK_SET
);
150 for (i
= 0; i
< MAX_PAGES
; i
++) {
151 Page
*p
= &anm
->pt
[i
];
152 p
->base_record
= avio_rl16(pb
);
153 p
->nb_records
= avio_rl16(pb
);
154 p
->size
= avio_rl16(pb
);
157 /* find page of first frame */
158 anm
->page
= find_record(anm
, 0);
168 av_log_ask_for_sample(s
, NULL
);
169 ret
= AVERROR_PATCHWELCOME
;
175 static int read_packet(AVFormatContext
*s
,
178 AnmDemuxContext
*anm
= s
->priv_data
;
179 AVIOContext
*pb
= s
->pb
;
181 int tmp
, record_size
;
183 if (s
->pb
->eof_reached
)
190 p
= &anm
->pt
[anm
->page
];
192 /* parse page header */
193 if (anm
->record
< 0) {
194 avio_seek(pb
, anm
->page_table_offset
+ MAX_PAGES
*6 + (anm
->page
<<16), SEEK_SET
);
195 avio_skip(pb
, 8 + 2*p
->nb_records
);
199 /* if we have fetched all records in this page, then find the
200 next page and repeat */
201 if (anm
->record
>= p
->nb_records
) {
202 anm
->page
= find_record(anm
, p
->base_record
+ p
->nb_records
);
209 /* fetch record size */
211 avio_seek(pb
, anm
->page_table_offset
+ MAX_PAGES
*6 + (anm
->page
<<16) +
212 8 + anm
->record
* 2, SEEK_SET
);
213 record_size
= avio_rl16(pb
);
214 avio_seek(pb
, tmp
, SEEK_SET
);
217 pkt
->size
= av_get_packet(s
->pb
, pkt
, record_size
);
220 if (p
->base_record
+ anm
->record
== 0)
221 pkt
->flags
|= AV_PKT_FLAG_KEY
;
227 AVInputFormat ff_anm_demuxer
= {
229 .long_name
= NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),
230 .priv_data_size
= sizeof(AnmDemuxContext
),
232 .read_header
= read_header
,
233 .read_packet
= read_packet
,