Mercurial > mplayer.hg
annotate libmpdemux/demux_aac.c @ 20658:ed20cbab07a4
Corrigendum 1
change chapter_id from v to s to allow negative chapter_id as required by the spec text
change was unanimously accepted (rich, oded, myself)
this change should not break any existing muxers or demuxers, with the exception of
assumtations about (non)overlapping chapters
author | michael |
---|---|
date | Sat, 04 Nov 2006 22:01:51 +0000 |
parents | c528c6c518f1 |
children | d7b2fa4c39da |
rev | line source |
---|---|
15720 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 | |
5 #include "config.h" | |
6 #include "mp_msg.h" | |
7 #include "help_mp.h" | |
8 | |
9 #include "stream.h" | |
10 #include "demuxer.h" | |
11 #include "parse_es.h" | |
12 #include "stheader.h" | |
13 | |
14 #include "bswap.h" | |
15 #include "ms_hdr.h" | |
16 | |
17 typedef struct { | |
18 uint8_t *buf; | |
19 uint64_t size; /// amount of time of data packets pushed to demuxer->audio (in bytes) | |
20 float time; /// amount of time elapsed based upon samples_per_frame/sample_rate (in milliseconds) | |
21 float last_pts; /// last pts seen | |
22 int bitrate; /// bitrate computed as size/time | |
23 } aac_priv_t; | |
24 | |
25 /// \param srate (out) sample rate | |
26 /// \param num (out) number of audio frames in this ADTS frame | |
27 /// \return size of the ADTS frame in bytes | |
28 /// aac_parse_frames needs a buffer at least 8 bytes long | |
29 int aac_parse_frame(uint8_t *buf, int *srate, int *num) | |
30 { | |
31 int i = 0, sr, fl = 0, id; | |
32 static int srates[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0, 0, 0}; | |
33 | |
34 if((buf[i] != 0xFF) || ((buf[i+1] & 0xF6) != 0xF0)) | |
35 return 0; | |
36 | |
37 id = (buf[i+1] >> 3) & 0x01; //id=1 mpeg2, 0: mpeg4 | |
38 sr = (buf[i+2] >> 2) & 0x0F; | |
39 if(sr > 11) | |
40 return 0; | |
41 *srate = srates[sr]; | |
42 | |
43 fl = ((buf[i+3] & 0x03) << 11) | (buf[i+4] << 3) | ((buf[i+5] >> 5) & 0x07); | |
44 *num = (buf[i+6] & 0x02) + 1; | |
45 | |
46 return fl; | |
47 } | |
48 | |
49 static int demux_aac_init(demuxer_t *demuxer) | |
50 { | |
51 aac_priv_t *priv; | |
52 | |
53 priv = calloc(1, sizeof(aac_priv_t)); | |
54 if(!priv) | |
55 return 0; | |
56 | |
57 priv->buf = (uint8_t*) malloc(8); | |
58 if(!priv->buf) | |
17789
9f0c42967ce5
fix minor (i.e. unlikely to ever happen) leak when init fails
reimar
parents:
17636
diff
changeset
|
59 { |
9f0c42967ce5
fix minor (i.e. unlikely to ever happen) leak when init fails
reimar
parents:
17636
diff
changeset
|
60 free(priv); |
15720 | 61 return 0; |
17789
9f0c42967ce5
fix minor (i.e. unlikely to ever happen) leak when init fails
reimar
parents:
17636
diff
changeset
|
62 } |
15720 | 63 |
64 demuxer->priv = priv; | |
65 return 1; | |
66 } | |
67 | |
16175 | 68 static void demux_close_aac(demuxer_t *demuxer) |
15720 | 69 { |
70 aac_priv_t *priv = (aac_priv_t *) demuxer->priv; | |
71 | |
72 if(!priv) | |
73 return; | |
74 | |
75 if(priv->buf) | |
76 free(priv->buf); | |
77 | |
78 free(demuxer->priv); | |
79 | |
80 return; | |
81 } | |
82 | |
16175 | 83 /// returns DEMUXER_TYPE_AAC if it finds 8 ADTS frames in 32768 bytes, 0 otherwise |
84 static int demux_aac_probe(demuxer_t *demuxer) | |
15720 | 85 { |
86 int cnt = 0, c, len, srate, num; | |
87 off_t init, probed; | |
88 aac_priv_t *priv; | |
89 | |
90 if(! demux_aac_init(demuxer)) | |
91 { | |
92 mp_msg(MSGT_DEMUX, MSGL_ERR, "COULDN'T INIT aac_demux, exit\n"); | |
93 return 0; | |
94 } | |
95 | |
96 priv = (aac_priv_t *) demuxer->priv; | |
97 | |
98 init = probed = stream_tell(demuxer->stream); | |
99 while(probed-init <= 32768 && cnt < 8) | |
100 { | |
101 c = 0; | |
102 while(c != 0xFF) | |
103 { | |
104 c = stream_read_char(demuxer->stream); | |
105 if(c < 0) | |
106 goto fail; | |
107 } | |
108 priv->buf[0] = 0xFF; | |
109 if(stream_read(demuxer->stream, &(priv->buf[1]), 7) < 7) | |
110 goto fail; | |
111 | |
112 len = aac_parse_frame(priv->buf, &srate, &num); | |
113 if(len > 0) | |
114 { | |
115 cnt++; | |
116 stream_skip(demuxer->stream, len - 8); | |
117 } | |
118 probed = stream_tell(demuxer->stream); | |
119 } | |
120 | |
121 stream_seek(demuxer->stream, init); | |
122 if(cnt < 8) | |
123 goto fail; | |
124 | |
16750
0a31740dd5e6
Use PRI?64 defines as format strings for 64 bit variables.
reimar
parents:
16175
diff
changeset
|
125 mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, INIT: %"PRIu64", PROBED: %"PRIu64", cnt: %d\n", init, probed, cnt); |
16175 | 126 return DEMUXER_TYPE_AAC; |
15720 | 127 |
128 fail: | |
129 mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, failed to detect an AAC stream\n"); | |
130 return 0; | |
131 } | |
132 | |
16175 | 133 static demuxer_t* demux_aac_open(demuxer_t *demuxer) |
15720 | 134 { |
135 sh_audio_t *sh; | |
136 | |
137 sh = new_sh_audio(demuxer, 0); | |
138 sh->ds = demuxer->audio; | |
139 sh->format = mmioFOURCC('M', 'P', '4', 'A'); | |
140 demuxer->audio->sh = sh; | |
141 | |
142 demuxer->filepos = stream_tell(demuxer->stream); | |
143 | |
16175 | 144 return demuxer; |
15720 | 145 } |
146 | |
16175 | 147 static int demux_aac_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) |
15720 | 148 { |
149 aac_priv_t *priv = (aac_priv_t *) demuxer->priv; | |
150 demux_packet_t *dp; | |
151 int c1, c2, len, srate, num; | |
152 float tm = 0; | |
153 | |
154 if(demuxer->stream->eof || (demuxer->movi_end && stream_tell(demuxer->stream) >= demuxer->movi_end)) | |
155 return 0; | |
156 | |
157 while(! demuxer->stream->eof) | |
158 { | |
159 c1 = c2 = 0; | |
160 while(c1 != 0xFF) | |
161 { | |
162 c1 = stream_read_char(demuxer->stream); | |
163 if(c1 < 0) | |
164 return 0; | |
165 } | |
166 c2 = stream_read_char(demuxer->stream); | |
167 if(c2 < 0) | |
168 return 0; | |
169 if((c2 & 0xF6) != 0xF0) | |
170 continue; | |
171 | |
172 priv->buf[0] = (unsigned char) c1; | |
173 priv->buf[1] = (unsigned char) c2; | |
174 if(stream_read(demuxer->stream, &(priv->buf[2]), 6) < 6) | |
175 return 0; | |
176 | |
177 len = aac_parse_frame(priv->buf, &srate, &num); | |
178 if(len > 0) | |
179 { | |
180 dp = new_demux_packet(len); | |
181 if(! dp) | |
182 { | |
183 mp_msg(MSGT_DEMUX, MSGL_ERR, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", len); | |
184 return 0; | |
185 } | |
186 | |
187 | |
188 memcpy(dp->buffer, priv->buf, 8); | |
189 stream_read(demuxer->stream, &(dp->buffer[8]), len-8); | |
190 if(srate) | |
191 tm = (float) (num * 1024.0/srate); | |
192 priv->last_pts += tm; | |
193 dp->pts = priv->last_pts; | |
194 //fprintf(stderr, "\nPTS: %.3f\n", dp->pts); | |
195 ds_add_packet(demuxer->audio, dp); | |
196 priv->size += len; | |
197 priv->time += tm; | |
198 | |
199 priv->bitrate = (int) (priv->size / priv->time); | |
200 demuxer->filepos = stream_tell(demuxer->stream); | |
201 | |
202 return len; | |
203 } | |
204 else | |
205 stream_skip(demuxer->stream, -6); | |
206 } | |
207 | |
208 return 0; | |
209 } | |
210 | |
211 | |
212 //This is an almost verbatim copy of high_res_mp3_seek(), from demux_audio.c | |
17636 | 213 static void demux_aac_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) |
15720 | 214 { |
215 aac_priv_t *priv = (aac_priv_t *) demuxer->priv; | |
216 demux_stream_t *d_audio=demuxer->audio; | |
217 sh_audio_t *sh_audio=d_audio->sh; | |
218 float time; | |
219 | |
220 ds_free_packs(d_audio); | |
221 | |
222 time = (flags & 1) ? rel_seek_secs - priv->last_pts : rel_seek_secs; | |
223 if(time < 0) | |
224 { | |
225 stream_seek(demuxer->stream, demuxer->movi_start); | |
226 time = priv->last_pts + time; | |
227 priv->last_pts = 0; | |
228 } | |
229 | |
230 if(time > 0) | |
231 { | |
232 int len, nf, srate, num; | |
233 | |
234 nf = time * sh_audio->samplerate/1024; | |
235 | |
236 while(nf > 0) | |
237 { | |
238 if(stream_read(demuxer->stream,priv->buf, 8) < 8) | |
239 break; | |
240 len = aac_parse_frame(priv->buf, &srate, &num); | |
241 if(len <= 0) | |
242 { | |
243 stream_skip(demuxer->stream, -7); | |
244 continue; | |
245 } | |
246 stream_skip(demuxer->stream, len - 8); | |
247 priv->last_pts += (float) (num*1024.0/srate); | |
248 nf -= num; | |
249 } | |
250 } | |
251 } | |
252 | |
16175 | 253 |
254 demuxer_desc_t demuxer_desc_aac = { | |
255 "AAC demuxer", | |
256 "aac", | |
257 "AAC", | |
258 "Nico Sabbi", | |
259 "Raw AAC files ", | |
260 DEMUXER_TYPE_AAC, | |
261 0, // unsafe autodetect | |
262 demux_aac_probe, | |
263 demux_aac_fill_buffer, | |
264 demux_aac_open, | |
265 demux_close_aac, | |
266 demux_aac_seek, | |
267 NULL | |
268 }; |