Mercurial > libavformat.hg
annotate dxa.c @ 5639:829780403fc6 libavformat
Make sure the header value used to avoid repeating headers on seeking to the
start and to avoid initializing codecs with missing headers is set for all streams.
Fixes issue 1723.
author | reimar |
---|---|
date | Mon, 08 Feb 2010 20:25:36 +0000 |
parents | 7c0b8cd87f5a |
children | 536e5527c1e0 |
rev | line source |
---|---|
1918 | 1 /* |
2 * DXA demuxer | |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4201
diff
changeset
|
3 * Copyright (c) 2007 Konstantin Shishkov |
1918 | 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 | |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
3424
diff
changeset
|
22 #include "libavutil/intreadwrite.h" |
1918 | 23 #include "avformat.h" |
24 #include "riff.h" | |
25 | |
26 #define DXA_EXTRA_SIZE 9 | |
27 | |
28 typedef struct{ | |
29 int frames; | |
30 int has_sound; | |
31 int bpc; | |
32 uint32_t bytes_left; | |
33 int64_t wavpos, vidpos; | |
34 int readvid; | |
35 }DXAContext; | |
36 | |
37 static int dxa_probe(AVProbeData *p) | |
38 { | |
5216
7c0b8cd87f5a
Improve dxa probe by checking the values for width and height are reasonable.
reimar
parents:
5058
diff
changeset
|
39 int w, h; |
7c0b8cd87f5a
Improve dxa probe by checking the values for width and height are reasonable.
reimar
parents:
5058
diff
changeset
|
40 if (p->buf_size < 15) |
7c0b8cd87f5a
Improve dxa probe by checking the values for width and height are reasonable.
reimar
parents:
5058
diff
changeset
|
41 return 0; |
7c0b8cd87f5a
Improve dxa probe by checking the values for width and height are reasonable.
reimar
parents:
5058
diff
changeset
|
42 w = AV_RB16(p->buf + 11); |
7c0b8cd87f5a
Improve dxa probe by checking the values for width and height are reasonable.
reimar
parents:
5058
diff
changeset
|
43 h = AV_RB16(p->buf + 13); |
1918 | 44 /* check file header */ |
45 if (p->buf[0] == 'D' && p->buf[1] == 'E' && | |
5216
7c0b8cd87f5a
Improve dxa probe by checking the values for width and height are reasonable.
reimar
parents:
5058
diff
changeset
|
46 p->buf[2] == 'X' && p->buf[3] == 'A' && |
7c0b8cd87f5a
Improve dxa probe by checking the values for width and height are reasonable.
reimar
parents:
5058
diff
changeset
|
47 w && w <= 2048 && h && h <= 2048) |
1918 | 48 return AVPROBE_SCORE_MAX; |
49 else | |
50 return 0; | |
51 } | |
52 | |
53 static int dxa_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
54 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
55 ByteIOContext *pb = s->pb; |
1918 | 56 DXAContext *c = s->priv_data; |
57 AVStream *st, *ast; | |
58 uint32_t tag; | |
59 int32_t fps; | |
60 int w, h; | |
61 int num, den; | |
62 int flags; | |
63 | |
64 tag = get_le32(pb); | |
65 if (tag != MKTAG('D', 'E', 'X', 'A')) | |
66 return -1; | |
67 flags = get_byte(pb); | |
68 c->frames = get_be16(pb); | |
69 if(!c->frames){ | |
70 av_log(s, AV_LOG_ERROR, "File contains no frames ???\n"); | |
71 return -1; | |
72 } | |
73 | |
74 fps = get_be32(pb); | |
75 if(fps > 0){ | |
76 den = 1000; | |
77 num = fps; | |
78 }else if (fps < 0){ | |
79 den = 100000; | |
80 num = -fps; | |
81 }else{ | |
82 den = 10; | |
83 num = 1; | |
84 } | |
85 w = get_be16(pb); | |
86 h = get_be16(pb); | |
87 c->has_sound = 0; | |
88 | |
89 st = av_new_stream(s, 0); | |
90 if (!st) | |
91 return -1; | |
92 | |
93 // Parse WAV data header | |
94 if(get_le32(pb) == MKTAG('W', 'A', 'V', 'E')){ | |
95 uint32_t size, fsize; | |
96 c->has_sound = 1; | |
97 size = get_be32(pb); | |
98 c->vidpos = url_ftell(pb) + size; | |
99 url_fskip(pb, 16); | |
100 fsize = get_le32(pb); | |
101 | |
102 ast = av_new_stream(s, 0); | |
103 if (!ast) | |
104 return -1; | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
4251
diff
changeset
|
105 ff_get_wav_header(pb, ast->codec, fsize); |
1918 | 106 // find 'data' chunk |
107 while(url_ftell(pb) < c->vidpos && !url_feof(pb)){ | |
108 tag = get_le32(pb); | |
109 fsize = get_le32(pb); | |
110 if(tag == MKTAG('d', 'a', 't', 'a')) break; | |
111 url_fskip(pb, fsize); | |
112 } | |
113 c->bpc = (fsize + c->frames - 1) / c->frames; | |
114 if(ast->codec->block_align) | |
115 c->bpc = ((c->bpc + ast->codec->block_align - 1) / ast->codec->block_align) * ast->codec->block_align; | |
116 c->bytes_left = fsize; | |
117 c->wavpos = url_ftell(pb); | |
118 url_fseek(pb, c->vidpos, SEEK_SET); | |
119 } | |
120 | |
121 /* now we are ready: build format streams */ | |
122 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
123 st->codec->codec_id = CODEC_ID_DXA; | |
124 st->codec->width = w; | |
125 st->codec->height = h; | |
126 av_reduce(&den, &num, den, num, (1UL<<31)-1); | |
127 av_set_pts_info(st, 33, num, den); | |
128 /* flags & 0x80 means that image is interlaced, | |
129 * flags & 0x40 means that image has double height | |
130 * either way set true height | |
131 */ | |
132 if(flags & 0xC0){ | |
133 st->codec->height >>= 1; | |
134 } | |
135 c->readvid = !c->has_sound; | |
136 c->vidpos = url_ftell(pb); | |
137 s->start_time = 0; | |
138 s->duration = (int64_t)c->frames * AV_TIME_BASE * num / den; | |
139 av_log(s, AV_LOG_DEBUG, "%d frame(s)\n",c->frames); | |
140 | |
141 return 0; | |
142 } | |
143 | |
144 static int dxa_read_packet(AVFormatContext *s, AVPacket *pkt) | |
145 { | |
146 DXAContext *c = s->priv_data; | |
147 int ret; | |
148 uint32_t size; | |
149 uint8_t buf[DXA_EXTRA_SIZE], pal[768+4]; | |
150 int pal_size = 0; | |
151 | |
152 if(!c->readvid && c->has_sound && c->bytes_left){ | |
153 c->readvid = 1; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
154 url_fseek(s->pb, c->wavpos, SEEK_SET); |
1918 | 155 size = FFMIN(c->bytes_left, c->bpc); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
156 ret = av_get_packet(s->pb, pkt, size); |
1918 | 157 pkt->stream_index = 1; |
158 if(ret != size) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
159 return AVERROR(EIO); |
1918 | 160 c->bytes_left -= size; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
161 c->wavpos = url_ftell(s->pb); |
1918 | 162 return 0; |
163 } | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
164 url_fseek(s->pb, c->vidpos, SEEK_SET); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
165 while(!url_feof(s->pb) && c->frames){ |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
166 get_buffer(s->pb, buf, 4); |
1918 | 167 switch(AV_RL32(buf)){ |
168 case MKTAG('N', 'U', 'L', 'L'): | |
169 if(av_new_packet(pkt, 4 + pal_size) < 0) | |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2001
diff
changeset
|
170 return AVERROR(ENOMEM); |
1918 | 171 pkt->stream_index = 0; |
172 if(pal_size) memcpy(pkt->data, pal, pal_size); | |
173 memcpy(pkt->data + pal_size, buf, 4); | |
174 c->frames--; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
175 c->vidpos = url_ftell(s->pb); |
1918 | 176 c->readvid = 0; |
177 return 0; | |
178 case MKTAG('C', 'M', 'A', 'P'): | |
179 pal_size = 768+4; | |
180 memcpy(pal, buf, 4); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
181 get_buffer(s->pb, pal + 4, 768); |
1918 | 182 break; |
183 case MKTAG('F', 'R', 'A', 'M'): | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
184 get_buffer(s->pb, buf + 4, DXA_EXTRA_SIZE - 4); |
1918 | 185 size = AV_RB32(buf + 5); |
186 if(size > 0xFFFFFF){ | |
187 av_log(s, AV_LOG_ERROR, "Frame size is too big: %d\n", size); | |
188 return -1; | |
189 } | |
190 if(av_new_packet(pkt, size + DXA_EXTRA_SIZE + pal_size) < 0) | |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2001
diff
changeset
|
191 return AVERROR(ENOMEM); |
1918 | 192 memcpy(pkt->data + pal_size, buf, DXA_EXTRA_SIZE); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
193 ret = get_buffer(s->pb, pkt->data + DXA_EXTRA_SIZE + pal_size, size); |
1918 | 194 if(ret != size){ |
195 av_free_packet(pkt); | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
196 return AVERROR(EIO); |
1918 | 197 } |
198 if(pal_size) memcpy(pkt->data, pal, pal_size); | |
199 pkt->stream_index = 0; | |
200 c->frames--; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
201 c->vidpos = url_ftell(s->pb); |
1918 | 202 c->readvid = 0; |
203 return 0; | |
204 default: | |
205 av_log(s, AV_LOG_ERROR, "Unknown tag %c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]); | |
206 return -1; | |
207 } | |
208 } | |
209 return AVERROR(EIO); | |
210 } | |
211 | |
212 AVInputFormat dxa_demuxer = { | |
213 "dxa", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
2771
diff
changeset
|
214 NULL_IF_CONFIG_SMALL("DXA"), |
1918 | 215 sizeof(DXAContext), |
216 dxa_probe, | |
217 dxa_read_header, | |
218 dxa_read_packet, | |
219 }; |