Mercurial > libavformat.hg
annotate anm.c @ 6435:67433b0c29d5 libavformat
move h264 demuxer to its own file
author | aurel |
---|---|
date | Sun, 29 Aug 2010 21:28:51 +0000 |
parents | c4ff37db69e1 |
children |
rev | line source |
---|---|
5510 | 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 /** | |
5969
178de7695c6c
Remove explicit filename from Doxygen @file commands.
diego
parents:
5913
diff
changeset
|
23 * @file |
5510 | 24 * Deluxe Paint Animation demuxer |
25 */ | |
26 | |
27 #include "libavutil/intreadwrite.h" | |
28 #include "avformat.h" | |
29 | |
30 typedef struct { | |
31 int base_record; | |
32 unsigned int nb_records; | |
33 int size; | |
34 } Page; | |
35 | |
36 typedef struct { | |
6330 | 37 unsigned int nb_pages; /**< total pages in file */ |
38 unsigned int nb_records; /**< total records in file */ | |
5510 | 39 int page_table_offset; |
6330 | 40 #define MAX_PAGES 256 /**< Deluxe Paint hardcoded value */ |
41 Page pt[MAX_PAGES]; /**< page table */ | |
42 int page; /**< current page (or AVERROR_xxx code) */ | |
43 int record; /**< current record (with in page) */ | |
5510 | 44 } AnmDemuxContext; |
45 | |
46 #define LPF_TAG MKTAG('L','P','F',' ') | |
47 #define ANIM_TAG MKTAG('A','N','I','M') | |
48 | |
49 static int probe(AVProbeData *p) | |
50 { | |
51 /* verify tags and video dimensions */ | |
52 if (AV_RL32(&p->buf[0]) == LPF_TAG && | |
53 AV_RL32(&p->buf[16]) == ANIM_TAG && | |
54 AV_RL16(&p->buf[20]) && AV_RL16(&p->buf[22])) | |
55 return AVPROBE_SCORE_MAX; | |
56 return 0; | |
57 } | |
58 | |
59 /** | |
60 * @return page containing the requested record or AVERROR_XXX | |
61 */ | |
62 static int find_record(const AnmDemuxContext *anm, int record) | |
63 { | |
64 int i; | |
65 | |
66 if (record >= anm->nb_records) | |
67 return AVERROR_EOF; | |
68 | |
69 for (i = 0; i < MAX_PAGES; i++) { | |
70 const Page *p = &anm->pt[i]; | |
71 if (p->nb_records > 0 && record >= p->base_record && record < p->base_record + p->nb_records) | |
72 return i; | |
73 } | |
74 | |
75 return AVERROR_INVALIDDATA; | |
76 } | |
77 | |
78 static int read_header(AVFormatContext *s, | |
79 AVFormatParameters *ap) | |
80 { | |
81 AnmDemuxContext *anm = s->priv_data; | |
82 ByteIOContext *pb = s->pb; | |
83 AVStream *st; | |
84 int i, ret; | |
85 | |
86 url_fskip(pb, 4); /* magic number */ | |
87 if (get_le16(pb) != MAX_PAGES) { | |
88 av_log_ask_for_sample(s, "max_pages != " AV_STRINGIFY(MAX_PAGES) "\n"); | |
89 return AVERROR_INVALIDDATA; | |
90 } | |
91 | |
92 anm->nb_pages = get_le16(pb); | |
93 anm->nb_records = get_le32(pb); | |
94 url_fskip(pb, 2); /* max records per page */ | |
95 anm->page_table_offset = get_le16(pb); | |
96 if (get_le32(pb) != ANIM_TAG) | |
97 return AVERROR_INVALIDDATA; | |
98 | |
99 /* video stream */ | |
100 st = av_new_stream(s, 0); | |
101 if (!st) | |
102 return AVERROR(ENOMEM); | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5652
diff
changeset
|
103 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
5510 | 104 st->codec->codec_id = CODEC_ID_ANM; |
105 st->codec->codec_tag = 0; /* no fourcc */ | |
106 st->codec->width = get_le16(pb); | |
107 st->codec->height = get_le16(pb); | |
108 if (get_byte(pb) != 0) | |
109 goto invalid; | |
110 url_fskip(pb, 1); /* frame rate multiplier info */ | |
111 | |
112 /* ignore last delta record (used for looping) */ | |
113 if (get_byte(pb)) /* has_last_delta */ | |
114 anm->nb_records = FFMAX(anm->nb_records - 1, 0); | |
115 | |
116 url_fskip(pb, 1); /* last_delta_valid */ | |
117 | |
118 if (get_byte(pb) != 0) | |
119 goto invalid; | |
120 | |
121 if (get_byte(pb) != 1) | |
122 goto invalid; | |
123 | |
124 url_fskip(pb, 1); /* other recs per frame */ | |
125 | |
126 if (get_byte(pb) != 1) | |
127 goto invalid; | |
128 | |
129 url_fskip(pb, 32); /* record_types */ | |
130 st->nb_frames = get_le32(pb); | |
131 av_set_pts_info(st, 64, 1, get_le16(pb)); | |
132 url_fskip(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 ret = AVERROR(ENOMEM); | |
139 goto close_and_return; | |
140 } | |
141 ret = get_buffer(pb, st->codec->extradata, st->codec->extradata_size); | |
142 if (ret < 0) | |
143 goto close_and_return; | |
144 | |
145 /* read page table */ | |
146 ret = url_fseek(pb, anm->page_table_offset, SEEK_SET); | |
147 if (ret < 0) | |
148 goto close_and_return; | |
149 | |
150 for (i = 0; i < MAX_PAGES; i++) { | |
151 Page *p = &anm->pt[i]; | |
152 p->base_record = get_le16(pb); | |
153 p->nb_records = get_le16(pb); | |
154 p->size = get_le16(pb); | |
155 } | |
156 | |
157 /* find page of first frame */ | |
158 anm->page = find_record(anm, 0); | |
159 if (anm->page < 0) { | |
160 ret = anm->page; | |
161 goto close_and_return; | |
162 } | |
163 | |
164 anm->record = -1; | |
165 return 0; | |
166 | |
167 invalid: | |
168 av_log_ask_for_sample(s, NULL); | |
169 ret = AVERROR_INVALIDDATA; | |
170 | |
171 close_and_return: | |
172 av_close_input_stream(s); | |
173 return ret; | |
174 } | |
175 | |
176 static int read_packet(AVFormatContext *s, | |
177 AVPacket *pkt) | |
178 { | |
179 AnmDemuxContext *anm = s->priv_data; | |
180 ByteIOContext *pb = s->pb; | |
181 Page *p; | |
182 int tmp, record_size; | |
183 | |
184 if (url_feof(s->pb)) | |
185 return AVERROR(EIO); | |
186 | |
187 if (anm->page < 0) | |
5652
7878a002f87d
Make DeluxePaint Animation demuxer actually return the find_record() error code (issue 1739).
pross
parents:
5510
diff
changeset
|
188 return anm->page; |
5510 | 189 |
190 repeat: | |
191 p = &anm->pt[anm->page]; | |
192 | |
193 /* parse page header */ | |
194 if (anm->record < 0) { | |
195 url_fseek(pb, anm->page_table_offset + MAX_PAGES*6 + (anm->page<<16), SEEK_SET); | |
196 url_fskip(pb, 8 + 2*p->nb_records); | |
197 anm->record = 0; | |
198 } | |
199 | |
200 /* if we have fetched all records in this page, then find the | |
201 next page and repeat */ | |
202 if (anm->record >= p->nb_records) { | |
203 anm->page = find_record(anm, p->base_record + p->nb_records); | |
204 if (anm->page < 0) | |
205 return anm->page; | |
206 anm->record = -1; | |
207 goto repeat; | |
208 } | |
209 | |
210 /* fetch record size */ | |
211 tmp = url_ftell(pb); | |
212 url_fseek(pb, anm->page_table_offset + MAX_PAGES*6 + (anm->page<<16) + | |
213 8 + anm->record * 2, SEEK_SET); | |
214 record_size = get_le16(pb); | |
215 url_fseek(pb, tmp, SEEK_SET); | |
216 | |
217 /* fetch record */ | |
218 pkt->size = av_get_packet(s->pb, pkt, record_size); | |
219 if (pkt->size < 0) | |
220 return pkt->size; | |
221 if (p->base_record + anm->record == 0) | |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
222 pkt->flags |= AV_PKT_FLAG_KEY; |
5510 | 223 |
224 anm->record++; | |
225 return 0; | |
226 } | |
227 | |
228 AVInputFormat anm_demuxer = { | |
229 "anm", | |
230 NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"), | |
231 sizeof(AnmDemuxContext), | |
232 probe, | |
233 read_header, | |
234 read_packet, | |
235 }; |