Mercurial > libavformat.hg
annotate dxa.c @ 5836:2997c88028cd libavformat
Move the probe loop from av_open_input_file() into its own method
av_probe_input_buffer() so that it can be reused. Here are a few
differences to the original way things were probed:
- maximum probe buffer size can be specified as a parameter.
- offset within the stream to probe from can be specified as a parameter.
- instead of seeking back to the start each time a probe fails, stream
data is appended to the reallocated buffer. This lowers the amount
of data read from the stream (there is no repetition) and results in
fewer closed and reopened streams (when seeking fails).
New attempt after r22296, which was revert in r22315 due to a FATE
failure.
See the thread:
Subject: [FFmpeg-devel] [PATCH] Move av_open_input_file probe loop to its own method
Date: 2010-03-05 03:23:57 GMT
Patch by Micah F. Galizia printf("%s%s@%s.%s", "micah", "galizia", "gmail", "com").
author | stefano |
---|---|
date | Sun, 14 Mar 2010 22:40:16 +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 }; |