Mercurial > mplayer.hg
annotate libmpdemux/demux_aac.c @ 28203:e6e0560eb50d
Synced with r28122
author | jheryan |
---|---|
date | Sat, 03 Jan 2009 02:15:07 +0000 |
parents | fa91545f01bb |
children | d643e4643313 |
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 | |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
21421
diff
changeset
|
9 #include "stream/stream.h" |
15720 | 10 #include "demuxer.h" |
11 #include "parse_es.h" | |
12 #include "stheader.h" | |
13 | |
14 #include "ms_hdr.h" | |
15 | |
16 typedef struct { | |
17 uint8_t *buf; | |
18 uint64_t size; /// amount of time of data packets pushed to demuxer->audio (in bytes) | |
19 float time; /// amount of time elapsed based upon samples_per_frame/sample_rate (in milliseconds) | |
20 float last_pts; /// last pts seen | |
21 int bitrate; /// bitrate computed as size/time | |
22 } aac_priv_t; | |
23 | |
24 /// \param srate (out) sample rate | |
25 /// \param num (out) number of audio frames in this ADTS frame | |
26 /// \return size of the ADTS frame in bytes | |
27 /// aac_parse_frames needs a buffer at least 8 bytes long | |
26327
fa91545f01bb
Split the aac header parsing out of aac demuxer to allow using libmpmux
albeu
parents:
26299
diff
changeset
|
28 int aac_parse_frame(uint8_t *buf, int *srate, int *num); |
15720 | 29 |
30 static int demux_aac_init(demuxer_t *demuxer) | |
31 { | |
32 aac_priv_t *priv; | |
33 | |
34 priv = calloc(1, sizeof(aac_priv_t)); | |
35 if(!priv) | |
36 return 0; | |
37 | |
38 priv->buf = (uint8_t*) malloc(8); | |
39 if(!priv->buf) | |
17789
9f0c42967ce5
fix minor (i.e. unlikely to ever happen) leak when init fails
reimar
parents:
17636
diff
changeset
|
40 { |
9f0c42967ce5
fix minor (i.e. unlikely to ever happen) leak when init fails
reimar
parents:
17636
diff
changeset
|
41 free(priv); |
15720 | 42 return 0; |
17789
9f0c42967ce5
fix minor (i.e. unlikely to ever happen) leak when init fails
reimar
parents:
17636
diff
changeset
|
43 } |
15720 | 44 |
45 demuxer->priv = priv; | |
46 return 1; | |
47 } | |
48 | |
16175 | 49 static void demux_close_aac(demuxer_t *demuxer) |
15720 | 50 { |
51 aac_priv_t *priv = (aac_priv_t *) demuxer->priv; | |
52 | |
53 if(!priv) | |
54 return; | |
55 | |
56 if(priv->buf) | |
57 free(priv->buf); | |
58 | |
59 free(demuxer->priv); | |
60 | |
61 return; | |
62 } | |
63 | |
16175 | 64 /// returns DEMUXER_TYPE_AAC if it finds 8 ADTS frames in 32768 bytes, 0 otherwise |
65 static int demux_aac_probe(demuxer_t *demuxer) | |
15720 | 66 { |
67 int cnt = 0, c, len, srate, num; | |
68 off_t init, probed; | |
69 aac_priv_t *priv; | |
70 | |
71 if(! demux_aac_init(demuxer)) | |
72 { | |
73 mp_msg(MSGT_DEMUX, MSGL_ERR, "COULDN'T INIT aac_demux, exit\n"); | |
74 return 0; | |
75 } | |
76 | |
77 priv = (aac_priv_t *) demuxer->priv; | |
78 | |
79 init = probed = stream_tell(demuxer->stream); | |
80 while(probed-init <= 32768 && cnt < 8) | |
81 { | |
82 c = 0; | |
83 while(c != 0xFF) | |
84 { | |
85 c = stream_read_char(demuxer->stream); | |
86 if(c < 0) | |
87 goto fail; | |
88 } | |
89 priv->buf[0] = 0xFF; | |
90 if(stream_read(demuxer->stream, &(priv->buf[1]), 7) < 7) | |
91 goto fail; | |
92 | |
93 len = aac_parse_frame(priv->buf, &srate, &num); | |
94 if(len > 0) | |
95 { | |
96 cnt++; | |
97 stream_skip(demuxer->stream, len - 8); | |
98 } | |
99 probed = stream_tell(demuxer->stream); | |
100 } | |
101 | |
102 stream_seek(demuxer->stream, init); | |
103 if(cnt < 8) | |
104 goto fail; | |
105 | |
16750
0a31740dd5e6
Use PRI?64 defines as format strings for 64 bit variables.
reimar
parents:
16175
diff
changeset
|
106 mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, INIT: %"PRIu64", PROBED: %"PRIu64", cnt: %d\n", init, probed, cnt); |
16175 | 107 return DEMUXER_TYPE_AAC; |
15720 | 108 |
109 fail: | |
110 mp_msg(MSGT_DEMUX, MSGL_V, "demux_aac_probe, failed to detect an AAC stream\n"); | |
111 return 0; | |
112 } | |
113 | |
16175 | 114 static demuxer_t* demux_aac_open(demuxer_t *demuxer) |
15720 | 115 { |
116 sh_audio_t *sh; | |
117 | |
118 sh = new_sh_audio(demuxer, 0); | |
119 sh->ds = demuxer->audio; | |
120 sh->format = mmioFOURCC('M', 'P', '4', 'A'); | |
26299
4d56038ec730
Fix lots and lots of other demuxers broken by r26301
reimar
parents:
25883
diff
changeset
|
121 demuxer->audio->id = 0; |
15720 | 122 demuxer->audio->sh = sh; |
123 | |
124 demuxer->filepos = stream_tell(demuxer->stream); | |
125 | |
16175 | 126 return demuxer; |
15720 | 127 } |
128 | |
16175 | 129 static int demux_aac_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) |
15720 | 130 { |
131 aac_priv_t *priv = (aac_priv_t *) demuxer->priv; | |
132 demux_packet_t *dp; | |
133 int c1, c2, len, srate, num; | |
134 float tm = 0; | |
135 | |
136 if(demuxer->stream->eof || (demuxer->movi_end && stream_tell(demuxer->stream) >= demuxer->movi_end)) | |
137 return 0; | |
138 | |
139 while(! demuxer->stream->eof) | |
140 { | |
141 c1 = c2 = 0; | |
142 while(c1 != 0xFF) | |
143 { | |
144 c1 = stream_read_char(demuxer->stream); | |
145 if(c1 < 0) | |
146 return 0; | |
147 } | |
148 c2 = stream_read_char(demuxer->stream); | |
149 if(c2 < 0) | |
150 return 0; | |
151 if((c2 & 0xF6) != 0xF0) | |
152 continue; | |
153 | |
154 priv->buf[0] = (unsigned char) c1; | |
155 priv->buf[1] = (unsigned char) c2; | |
156 if(stream_read(demuxer->stream, &(priv->buf[2]), 6) < 6) | |
157 return 0; | |
158 | |
159 len = aac_parse_frame(priv->buf, &srate, &num); | |
160 if(len > 0) | |
161 { | |
162 dp = new_demux_packet(len); | |
163 if(! dp) | |
164 { | |
165 mp_msg(MSGT_DEMUX, MSGL_ERR, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", len); | |
166 return 0; | |
167 } | |
168 | |
169 | |
170 memcpy(dp->buffer, priv->buf, 8); | |
171 stream_read(demuxer->stream, &(dp->buffer[8]), len-8); | |
172 if(srate) | |
173 tm = (float) (num * 1024.0/srate); | |
174 priv->last_pts += tm; | |
175 dp->pts = priv->last_pts; | |
176 //fprintf(stderr, "\nPTS: %.3f\n", dp->pts); | |
177 ds_add_packet(demuxer->audio, dp); | |
178 priv->size += len; | |
179 priv->time += tm; | |
180 | |
181 priv->bitrate = (int) (priv->size / priv->time); | |
182 demuxer->filepos = stream_tell(demuxer->stream); | |
183 | |
184 return len; | |
185 } | |
186 else | |
187 stream_skip(demuxer->stream, -6); | |
188 } | |
189 | |
190 return 0; | |
191 } | |
192 | |
193 | |
194 //This is an almost verbatim copy of high_res_mp3_seek(), from demux_audio.c | |
17636 | 195 static void demux_aac_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) |
15720 | 196 { |
197 aac_priv_t *priv = (aac_priv_t *) demuxer->priv; | |
198 demux_stream_t *d_audio=demuxer->audio; | |
199 sh_audio_t *sh_audio=d_audio->sh; | |
200 float time; | |
201 | |
202 ds_free_packs(d_audio); | |
203 | |
25883
baf32110d3fc
Use defines to give names to the different seek flags.
reimar
parents:
25707
diff
changeset
|
204 time = (flags & SEEK_ABSOLUTE) ? rel_seek_secs - priv->last_pts : rel_seek_secs; |
15720 | 205 if(time < 0) |
206 { | |
207 stream_seek(demuxer->stream, demuxer->movi_start); | |
208 time = priv->last_pts + time; | |
209 priv->last_pts = 0; | |
210 } | |
211 | |
212 if(time > 0) | |
213 { | |
214 int len, nf, srate, num; | |
215 | |
216 nf = time * sh_audio->samplerate/1024; | |
217 | |
218 while(nf > 0) | |
219 { | |
220 if(stream_read(demuxer->stream,priv->buf, 8) < 8) | |
221 break; | |
222 len = aac_parse_frame(priv->buf, &srate, &num); | |
223 if(len <= 0) | |
224 { | |
225 stream_skip(demuxer->stream, -7); | |
226 continue; | |
227 } | |
228 stream_skip(demuxer->stream, len - 8); | |
229 priv->last_pts += (float) (num*1024.0/srate); | |
230 nf -= num; | |
231 } | |
232 } | |
233 } | |
234 | |
16175 | 235 |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
22605
diff
changeset
|
236 const demuxer_desc_t demuxer_desc_aac = { |
16175 | 237 "AAC demuxer", |
238 "aac", | |
239 "AAC", | |
240 "Nico Sabbi", | |
241 "Raw AAC files ", | |
242 DEMUXER_TYPE_AAC, | |
243 0, // unsafe autodetect | |
244 demux_aac_probe, | |
245 demux_aac_fill_buffer, | |
246 demux_aac_open, | |
247 demux_close_aac, | |
248 demux_aac_seek, | |
249 NULL | |
250 }; |