FFmpeg
Loading...
Searching...
No Matches
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
28#include "avformat.h"
29#include "demux.h"
30#include "internal.h"
31
32typedef struct Page {
34 unsigned int nb_records;
35 int size;
36} Page;
37
38typedef struct AnmDemuxContext {
39 unsigned int nb_pages; /**< total pages in file */
40 unsigned int nb_records; /**< total records in file */
42#define MAX_PAGES 256 /**< Deluxe Paint hardcoded value */
43 Page pt[MAX_PAGES]; /**< page table */
44 int page; /**< current page (or AVERROR_xxx code) */
45 int record; /**< current record (with in page) */
47
48#define LPF_TAG MKTAG('L','P','F',' ')
49#define ANIM_TAG MKTAG('A','N','I','M')
50
51static int probe(const AVProbeData *p)
52{
53 /* verify tags and video dimensions */
54 if (AV_RL32(&p->buf[0]) == LPF_TAG &&
55 AV_RL32(&p->buf[16]) == ANIM_TAG &&
56 AV_RL16(&p->buf[20]) && AV_RL16(&p->buf[22]))
57 return AVPROBE_SCORE_MAX;
58 return 0;
59}
60
61/**
62 * @return page containing the requested record or AVERROR_XXX
63 */
64static int find_record(const AnmDemuxContext *anm, int record)
65{
66 int i;
67
68 if (record >= anm->nb_records)
69 return AVERROR_EOF;
70
71 for (i = 0; i < MAX_PAGES; i++) {
72 const Page *p = &anm->pt[i];
73 if (p->nb_records > 0 && record >= p->base_record && record < p->base_record + p->nb_records)
74 return i;
75 }
76
78}
79
81{
82 AnmDemuxContext *anm = s->priv_data;
83 AVIOContext *pb = s->pb;
84 AVStream *st;
85 int i, ret;
86
87 avio_skip(pb, 4); /* magic number */
88 if (avio_rl16(pb) != MAX_PAGES) {
91 }
92
93 anm->nb_pages = avio_rl16(pb);
94 anm->nb_records = avio_rl32(pb);
95 avio_skip(pb, 2); /* max records per page */
97 if (avio_rl32(pb) != ANIM_TAG)
99
100 /* video stream */
102 if (!st)
103 return AVERROR(ENOMEM);
106 st->codecpar->codec_tag = 0; /* no fourcc */
107 st->codecpar->width = avio_rl16(pb);
108 st->codecpar->height = avio_rl16(pb);
109 if (avio_r8(pb) != 0)
110 goto invalid;
111 avio_skip(pb, 1); /* frame rate multiplier info */
112
113 /* ignore last delta record (used for looping) */
114 if (avio_r8(pb)) /* has_last_delta */
115 anm->nb_records = FFMAX(anm->nb_records - 1, 0);
116
117 avio_skip(pb, 1); /* last_delta_valid */
118
119 if (avio_r8(pb) != 0)
120 goto invalid;
121
122 if (avio_r8(pb) != 1)
123 goto invalid;
124
125 avio_skip(pb, 1); /* other recs per frame */
126
127 if (avio_r8(pb) != 1)
128 goto invalid;
129
130 avio_skip(pb, 32); /* record_types */
131 st->nb_frames = avio_rl32(pb);
132 avpriv_set_pts_info(st, 64, 1, avio_rl16(pb));
133 avio_skip(pb, 58);
134
135 /* color cycling and palette data */
136 ret = ff_get_extradata(s, st->codecpar, s->pb, 16*8 + 4*256);
137 if (ret < 0)
138 return ret;
139
140 /* read page table */
141 ret = avio_seek(pb, anm->page_table_offset, SEEK_SET);
142 if (ret < 0)
143 return ret;
144
145 for (i = 0; i < MAX_PAGES; i++) {
146 Page *p = &anm->pt[i];
147 p->base_record = avio_rl16(pb);
148 p->nb_records = avio_rl16(pb);
149 p->size = avio_rl16(pb);
150 }
151
152 /* find page of first frame */
153 anm->page = find_record(anm, 0);
154 if (anm->page < 0) {
155 return anm->page;
156 }
157
158 anm->record = -1;
159 return 0;
160
161invalid:
162 avpriv_request_sample(s, "Invalid header element");
164}
165
167 AVPacket *pkt)
168{
169 AnmDemuxContext *anm = s->priv_data;
170 AVIOContext *pb = s->pb;
171 Page *p;
172 int tmp, record_size;
173
174 if (avio_feof(s->pb))
175 return AVERROR_EOF;
176
177 if (anm->page < 0)
178 return anm->page;
179
180repeat:
181 p = &anm->pt[anm->page];
182
183 /* parse page header */
184 if (anm->record < 0) {
185 avio_seek(pb, anm->page_table_offset + MAX_PAGES*6 + (anm->page<<16), SEEK_SET);
186 avio_skip(pb, 8 + 2*p->nb_records);
187 anm->record = 0;
188 }
189
190 /* if we have fetched all records in this page, then find the
191 next page and repeat */
192 if (anm->record >= p->nb_records) {
193 anm->page = find_record(anm, p->base_record + p->nb_records);
194 if (anm->page < 0)
195 return anm->page;
196 anm->record = -1;
197 goto repeat;
198 }
199
200 /* fetch record size */
201 tmp = avio_tell(pb);
202 avio_seek(pb, anm->page_table_offset + MAX_PAGES*6 + (anm->page<<16) +
203 8 + anm->record * 2, SEEK_SET);
204 record_size = avio_rl16(pb);
205 avio_seek(pb, tmp, SEEK_SET);
206
207 /* fetch record */
208 pkt->size = av_get_packet(s->pb, pkt, record_size);
209 if (pkt->size < 0)
210 return pkt->size;
211 if (p->base_record + anm->record == 0)
212 pkt->flags |= AV_PKT_FLAG_KEY;
213
214 anm->record++;
215 return 0;
216}
217
219 .p.name = "anm",
220 .p.long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),
221 .priv_data_size = sizeof(AnmDemuxContext),
222 .read_probe = probe,
225};
static int probe(const AVProbeData *p)
Definition act.c:39
const FFInputFormat ff_anm_demuxer
Definition anm.c:218
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
#define AVPROBE_SCORE_MAX
maximum score
Definition avformat.h:483
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition utils.c:98
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
unsigned int avio_rl16(AVIOContext *s)
Definition aviobuf.c:717
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition aviobuf.c:321
unsigned int avio_rl32(AVIOContext *s)
Definition aviobuf.c:733
int avio_r8(AVIOContext *s)
Definition aviobuf.c:606
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
static int read_probe(const AVProbeData *p)
Definition cdg.c:30
#define NULL
Definition coverity.c:32
int ff_get_extradata(void *logctx, AVCodecParameters *par, AVIOContext *pb, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0 and f...
static AVPacket * pkt
static int read_header(FFV1Context *f, RangeCoder *c)
Definition ffv1dec.c:578
@ AV_CODEC_ID_ANM
Definition codec_id.h:184
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define AV_STRINGIFY(s)
Definition macros.h:66
#define AV_RL32(p)
#define AV_RL16(p)
#define ANIM_TAG
Definition anm.c:49
static int read_packet(AVFormatContext *s, AVPacket *pkt)
Definition anm.c:166
#define MAX_PAGES
Deluxe Paint hardcoded value.
Definition anm.c:42
#define LPF_TAG
Definition anm.c:48
static int read_header(AVFormatContext *s)
Definition anm.c:80
static int find_record(const AnmDemuxContext *anm, int record)
Definition anm.c:64
static int probe(const AVProbeData *p)
Definition anm.c:51
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
#define FFMAX(a, b)
Definition macros.h:47
int height
The height of the video frame in pixels.
Definition codec_par.h:150
int width
The width of the video frame in pixels.
Definition codec_par.h:143
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition codec_par.h:61
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
Format I/O context.
Definition avformat.h:1333
Bytestream IO Context.
Definition avio.h:160
This structure stores compressed data.
Definition packet.h:580
This structure contains the data a format has to probe a file.
Definition avformat.h:471
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
int64_t nb_frames
number of frames in this stream if known or 0
Definition avformat.h:827
Page pt[MAX_PAGES]
page table
Definition anm.c:43
int record
current record (with in page)
Definition anm.c:45
int page
current page (or AVERROR_xxx code)
Definition anm.c:44
int page_table_offset
Definition anm.c:41
unsigned int nb_pages
total pages in file
Definition anm.c:39
unsigned int nb_records
total records in file
Definition anm.c:40
Definition anm.c:32
unsigned int nb_records
Definition anm.c:34
int base_record
Definition anm.c:33
int size
Definition anm.c:35
#define avpriv_request_sample(...)
static uint8_t tmp[40]
Definition aes_ctr.c:52