Mercurial > libavformat.hg
annotate dxa.c @ 3068:9cc9ff5aff9c libavformat
set bps to uncompressed original sound data for compressed audio
according to aiff specs, qt set it to 16 for mace and ima4,
fail if block align is not set.
author | bcoudurier |
---|---|
date | Mon, 25 Feb 2008 12:00:31 +0000 |
parents | d52c718e83f9 |
children | 7a0230981402 |
rev | line source |
---|---|
1918 | 1 /* |
2 * DXA demuxer | |
3 * Copyright (c) 2007 Konstantin Shishkov. | |
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 #include "avformat.h" | |
23 #include "riff.h" | |
24 | |
25 #define DXA_EXTRA_SIZE 9 | |
26 | |
27 typedef struct{ | |
28 int frames; | |
29 int has_sound; | |
30 int bpc; | |
31 uint32_t bytes_left; | |
32 int64_t wavpos, vidpos; | |
33 int readvid; | |
34 }DXAContext; | |
35 | |
36 static int dxa_probe(AVProbeData *p) | |
37 { | |
38 /* check file header */ | |
39 if (p->buf[0] == 'D' && p->buf[1] == 'E' && | |
40 p->buf[2] == 'X' && p->buf[3] == 'A') | |
41 return AVPROBE_SCORE_MAX; | |
42 else | |
43 return 0; | |
44 } | |
45 | |
46 static int dxa_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
47 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
48 ByteIOContext *pb = s->pb; |
1918 | 49 DXAContext *c = s->priv_data; |
50 AVStream *st, *ast; | |
51 uint32_t tag; | |
52 int32_t fps; | |
53 int w, h; | |
54 int num, den; | |
55 int flags; | |
56 | |
57 tag = get_le32(pb); | |
58 if (tag != MKTAG('D', 'E', 'X', 'A')) | |
59 return -1; | |
60 flags = get_byte(pb); | |
61 c->frames = get_be16(pb); | |
62 if(!c->frames){ | |
63 av_log(s, AV_LOG_ERROR, "File contains no frames ???\n"); | |
64 return -1; | |
65 } | |
66 | |
67 fps = get_be32(pb); | |
68 if(fps > 0){ | |
69 den = 1000; | |
70 num = fps; | |
71 }else if (fps < 0){ | |
72 den = 100000; | |
73 num = -fps; | |
74 }else{ | |
75 den = 10; | |
76 num = 1; | |
77 } | |
78 w = get_be16(pb); | |
79 h = get_be16(pb); | |
80 c->has_sound = 0; | |
81 | |
82 st = av_new_stream(s, 0); | |
83 if (!st) | |
84 return -1; | |
85 | |
86 // Parse WAV data header | |
87 if(get_le32(pb) == MKTAG('W', 'A', 'V', 'E')){ | |
88 uint32_t size, fsize; | |
89 c->has_sound = 1; | |
90 size = get_be32(pb); | |
91 c->vidpos = url_ftell(pb) + size; | |
92 url_fskip(pb, 16); | |
93 fsize = get_le32(pb); | |
94 | |
95 ast = av_new_stream(s, 0); | |
96 if (!ast) | |
97 return -1; | |
98 get_wav_header(pb, ast->codec, fsize); | |
99 // find 'data' chunk | |
100 while(url_ftell(pb) < c->vidpos && !url_feof(pb)){ | |
101 tag = get_le32(pb); | |
102 fsize = get_le32(pb); | |
103 if(tag == MKTAG('d', 'a', 't', 'a')) break; | |
104 url_fskip(pb, fsize); | |
105 } | |
106 c->bpc = (fsize + c->frames - 1) / c->frames; | |
107 if(ast->codec->block_align) | |
108 c->bpc = ((c->bpc + ast->codec->block_align - 1) / ast->codec->block_align) * ast->codec->block_align; | |
109 c->bytes_left = fsize; | |
110 c->wavpos = url_ftell(pb); | |
111 url_fseek(pb, c->vidpos, SEEK_SET); | |
112 } | |
113 | |
114 /* now we are ready: build format streams */ | |
115 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
116 st->codec->codec_id = CODEC_ID_DXA; | |
117 st->codec->width = w; | |
118 st->codec->height = h; | |
119 av_reduce(&den, &num, den, num, (1UL<<31)-1); | |
120 av_set_pts_info(st, 33, num, den); | |
121 /* flags & 0x80 means that image is interlaced, | |
122 * flags & 0x40 means that image has double height | |
123 * either way set true height | |
124 */ | |
125 if(flags & 0xC0){ | |
126 st->codec->height >>= 1; | |
127 } | |
128 c->readvid = !c->has_sound; | |
129 c->vidpos = url_ftell(pb); | |
130 s->start_time = 0; | |
131 s->duration = (int64_t)c->frames * AV_TIME_BASE * num / den; | |
132 av_log(s, AV_LOG_DEBUG, "%d frame(s)\n",c->frames); | |
133 | |
134 return 0; | |
135 } | |
136 | |
137 static int dxa_read_packet(AVFormatContext *s, AVPacket *pkt) | |
138 { | |
139 DXAContext *c = s->priv_data; | |
140 int ret; | |
141 uint32_t size; | |
142 uint8_t buf[DXA_EXTRA_SIZE], pal[768+4]; | |
143 int pal_size = 0; | |
144 | |
145 if(!c->readvid && c->has_sound && c->bytes_left){ | |
146 c->readvid = 1; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
147 url_fseek(s->pb, c->wavpos, SEEK_SET); |
1918 | 148 size = FFMIN(c->bytes_left, c->bpc); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
149 ret = av_get_packet(s->pb, pkt, size); |
1918 | 150 pkt->stream_index = 1; |
151 if(ret != size) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
152 return AVERROR(EIO); |
1918 | 153 c->bytes_left -= size; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
154 c->wavpos = url_ftell(s->pb); |
1918 | 155 return 0; |
156 } | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
157 url_fseek(s->pb, c->vidpos, SEEK_SET); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
158 while(!url_feof(s->pb) && c->frames){ |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
159 get_buffer(s->pb, buf, 4); |
1918 | 160 switch(AV_RL32(buf)){ |
161 case MKTAG('N', 'U', 'L', 'L'): | |
162 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
|
163 return AVERROR(ENOMEM); |
1918 | 164 pkt->stream_index = 0; |
165 if(pal_size) memcpy(pkt->data, pal, pal_size); | |
166 memcpy(pkt->data + pal_size, buf, 4); | |
167 c->frames--; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
168 c->vidpos = url_ftell(s->pb); |
1918 | 169 c->readvid = 0; |
170 return 0; | |
171 case MKTAG('C', 'M', 'A', 'P'): | |
172 pal_size = 768+4; | |
173 memcpy(pal, buf, 4); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
174 get_buffer(s->pb, pal + 4, 768); |
1918 | 175 break; |
176 case MKTAG('F', 'R', 'A', 'M'): | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
177 get_buffer(s->pb, buf + 4, DXA_EXTRA_SIZE - 4); |
1918 | 178 size = AV_RB32(buf + 5); |
179 if(size > 0xFFFFFF){ | |
180 av_log(s, AV_LOG_ERROR, "Frame size is too big: %d\n", size); | |
181 return -1; | |
182 } | |
183 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
|
184 return AVERROR(ENOMEM); |
1918 | 185 memcpy(pkt->data + pal_size, buf, DXA_EXTRA_SIZE); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
186 ret = get_buffer(s->pb, pkt->data + DXA_EXTRA_SIZE + pal_size, size); |
1918 | 187 if(ret != size){ |
188 av_free_packet(pkt); | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
189 return AVERROR(EIO); |
1918 | 190 } |
191 if(pal_size) memcpy(pkt->data, pal, pal_size); | |
192 pkt->stream_index = 0; | |
193 c->frames--; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
194 c->vidpos = url_ftell(s->pb); |
1918 | 195 c->readvid = 0; |
196 return 0; | |
197 default: | |
198 av_log(s, AV_LOG_ERROR, "Unknown tag %c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]); | |
199 return -1; | |
200 } | |
201 } | |
202 return AVERROR(EIO); | |
203 } | |
204 | |
205 AVInputFormat dxa_demuxer = { | |
206 "dxa", | |
207 "dxa", | |
208 sizeof(DXAContext), | |
209 dxa_probe, | |
210 dxa_read_header, | |
211 dxa_read_packet, | |
212 }; |