Mercurial > mplayer.hg
annotate libmpdemux/demux_real.c @ 3905:91e5c563fce5
SSE added
author | arpi |
---|---|
date | Sun, 30 Dec 2001 20:26:19 +0000 |
parents | c5cefeb78c40 |
children | 701d18898835 |
rev | line source |
---|---|
3777 | 1 /* |
2 Real parser & demuxer | |
3 | |
4 (C) Alex Beregszaszi <alex@naxine.org> | |
5 | |
6 Based on FFmpeg's libav/rm.c. | |
7 */ | |
8 | |
3788 | 9 /* |
10 Some codecs for Real (from Mike Melanson): | |
11 | |
12 RV10: As has been mentioned, H.263-based; not an unreasonable guess | |
13 RV20: RealVideo 2.0, nothing known | |
14 RV30: RealVideo 3.0,nothing known, but I don't believe I've ever seen any | |
15 media encoded with it | |
16 DNET: apparently one of their original audio codecs, to be used with music | |
17 SIPR: SiprNet, based on ACELP, and is great for compressing voice | |
18 COKR(?): Cooker, the fabled G2 audio codec | |
3795 | 19 |
20 New infos: | |
21 | |
22 Audio codecs: (supported by RealPlayer8 for Linux) | |
23 ATRC - RealAudio 8 (ATRAC3) | |
24 COOK - RealAudio G2 | |
25 DNET - RealAudio 3.0 | |
26 SIPR - SiproLab's audio codec | |
27 | |
28 Video codecs: (supported by RealPlayer8 for Linux) | |
29 RV10 | |
30 RV20 | |
31 RV30 | |
3788 | 32 */ |
33 | |
3777 | 34 #include <stdio.h> |
35 #include <stdlib.h> | |
36 #include <unistd.h> | |
37 | |
38 #include "config.h" | |
39 #include "mp_msg.h" | |
40 #include "help_mp.h" | |
41 | |
42 #include "stream.h" | |
43 #include "demuxer.h" | |
44 #include "stheader.h" | |
45 #include "bswap.h" | |
46 | |
47 #define MKTAG(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24)) | |
48 | |
49 #define MAX_STREAMS 10 | |
50 | |
51 typedef struct { | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
52 /* for seeking */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
53 int index_chunk_offset; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
54 int *index_table[MAX_STREAMS]; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
55 int index_table_size[MAX_STREAMS]; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
56 int data_chunk_offset; |
3777 | 57 int num_of_packets; |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
58 int current_packet; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
59 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
60 /* stream id table */ |
3777 | 61 int last_a_stream; |
62 int a_streams[MAX_STREAMS]; | |
63 int last_v_stream; | |
64 int v_streams[MAX_STREAMS]; | |
65 } real_priv_t; | |
66 | |
67 static void get_str(int isbyte, demuxer_t *demuxer, char *buf, int buf_size) | |
68 { | |
69 int len, i; | |
70 char *q; | |
71 | |
72 if (isbyte) | |
73 len = stream_read_char(demuxer->stream); | |
74 else | |
75 len = stream_read_word(demuxer->stream); | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
76 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
77 stream_read(demuxer->stream, buf, (len > buf_size) ? buf_size : len); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
78 if (len > buf_size) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
79 stream_skip(demuxer->stream, len-buf_size); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
80 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
81 printf("read_str: %d bytes read\n", len); |
3777 | 82 } |
83 | |
84 static void skip_str(int isbyte, demuxer_t *demuxer) | |
85 { | |
86 int len; | |
87 | |
88 if (isbyte) | |
89 len = stream_read_char(demuxer->stream); | |
90 else | |
91 len = stream_read_word(demuxer->stream); | |
92 | |
93 stream_skip(demuxer->stream, len); | |
94 | |
95 printf("skip_str: %d bytes skipped\n", len); | |
96 } | |
97 | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
98 static void parse_index_chunk(demuxer_t *demuxer) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
99 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
100 real_priv_t *priv = demuxer->priv; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
101 int origpos = stream_tell(demuxer->stream); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
102 int i, entries; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
103 int stream_id = 0; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
104 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
105 printf("Building index table from index chunk (%d)\n", |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
106 priv->index_chunk_offset); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
107 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
108 stream_seek(demuxer->stream, priv->index_chunk_offset); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
109 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
110 stream_skip(demuxer->stream, 4); /* INDX */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
111 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
112 read_index: |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
113 if (stream_id > MAX_STREAMS) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
114 goto end; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
115 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
116 stream_skip(demuxer->stream, 8); /* unknown */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
117 entries = stream_read_word(demuxer->stream); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
118 printf("entries: %d\n", entries); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
119 if (entries <= 0) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
120 goto end; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
121 stream_skip(demuxer->stream, 12); /* unknown */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
122 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
123 // stream_skip(demuxer->stream, 22); /* unknown bytes */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
124 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
125 priv->index_table_size[stream_id] = entries; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
126 priv->index_table[stream_id] = malloc(priv->index_table_size[stream_id] * sizeof(int)); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
127 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
128 for (i = 0; i < entries; i++) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
129 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
130 priv->index_table[stream_id][i] = stream_read_dword(demuxer->stream); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
131 stream_skip(demuxer->stream, 10); /* unknown bytes */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
132 /* [position(dword)][unk1(word)][unused(dword)][unk2(word)] */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
133 printf("Index table: Stream#%d: entry: %d: pos: %d\n", |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
134 stream_id, i, priv->index_table[stream_id][i]); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
135 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
136 demuxer->seekable = 1; /* got index, we're able to seek */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
137 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
138 // stream_seek(demuxer->stream, stream_tell(demuxer->stream)-7); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
139 /* search next index table for other stream */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
140 i = stream_read_word(demuxer->stream); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
141 printf("pos: %d, next tag: %.4s\n", stream_tell(demuxer->stream), &i); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
142 if (i == MKTAG('I', 'N', 'D', 'X')) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
143 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
144 stream_id++; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
145 goto read_index; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
146 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
147 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
148 end: |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
149 if (entries == -256) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
150 stream_reset(demuxer->stream); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
151 stream_seek(demuxer->stream, origpos); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
152 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
153 |
3795 | 154 int real_check_file(demuxer_t* demuxer) |
155 { | |
3777 | 156 real_priv_t *priv; |
157 int c; | |
158 | |
159 mp_msg(MSGT_DEMUX,MSGL_V,"Checking for REAL\n"); | |
160 | |
161 c = stream_read_dword_le(demuxer->stream); | |
162 if (c == -256) | |
163 return 0; /* EOF */ | |
164 if (c != MKTAG('.', 'R', 'M', 'F')) | |
165 return 0; /* bad magic */ | |
166 | |
167 priv = malloc(sizeof(real_priv_t)); | |
168 memset(priv, 0, sizeof(real_priv_t)); | |
169 demuxer->priv = priv; | |
170 | |
171 return 1; | |
172 } | |
173 | |
174 // return value: | |
175 // 0 = EOF or no stream found | |
176 // 1 = successfully read a packet | |
177 int demux_real_fill_buffer(demuxer_t *demuxer) | |
178 { | |
179 real_priv_t *priv = demuxer->priv; | |
180 demux_stream_t *ds = NULL; | |
181 int len; | |
182 int timestamp; | |
183 int stream_id; | |
184 int i; | |
3795 | 185 int flags; |
3777 | 186 |
187 // printf("num_of_packets: %d\n", priv->num_of_packets); | |
188 | |
189 loop: | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
190 if ((priv->num_of_packets == 0) && (priv->num_of_packets != -10)) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
191 return 0; /* EOF */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
192 if (priv->current_packet > priv->num_of_packets) |
3777 | 193 return 0; /* EOF */ |
3795 | 194 stream_skip(demuxer->stream, 2); /* version */ |
3777 | 195 len = stream_read_word(demuxer->stream); |
196 if (len == -256) /* EOF */ | |
197 return 0; | |
198 if (len < 12) | |
199 { | |
200 printf("bad packet len (%d)\n", len); | |
201 stream_skip(demuxer->stream, len); | |
202 goto loop; | |
203 } | |
204 stream_id = stream_read_word(demuxer->stream); | |
205 timestamp = stream_read_dword(demuxer->stream); | |
206 | |
207 stream_skip(demuxer->stream, 1); /* reserved */ | |
3795 | 208 flags = stream_read_char(demuxer->stream); |
209 /* flags: */ | |
210 /* 0x2 - keyframe */ | |
211 | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
212 // printf("packet#%d: pos: %d, len: %d, stream_id: %d, timestamp: %d, flags: %x\n", |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
213 // priv->current_packet, stream_tell(demuxer->stream)-12, len, stream_id, timestamp, flags); |
3777 | 214 |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
215 // if (priv->num_of_packets != -10) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
216 // priv->num_of_packets--; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
217 priv->current_packet++; |
3777 | 218 len -= 12; |
219 | |
220 /* check if stream_id is audio stream */ | |
221 for (i = 0; i < priv->last_a_stream; i++) | |
222 { | |
223 if (priv->a_streams[i] == stream_id) | |
224 { | |
225 // printf("packet is audio (id: %d)\n", stream_id); | |
226 ds = demuxer->audio; /* FIXME */ | |
227 break; | |
228 } | |
229 } | |
230 /* check if stream_id is video stream */ | |
231 for (i = 0; i < priv->last_v_stream; i++) | |
232 { | |
233 if (priv->v_streams[i] == stream_id) | |
234 { | |
235 // printf("packet is video (id: %d)\n", stream_id); | |
236 ds = demuxer->video; /* FIXME */ | |
237 break; | |
238 } | |
239 } | |
240 | |
241 /* id not found */ | |
242 if (ds == NULL) | |
243 { | |
244 printf("unknown stream id (%d)\n", stream_id); | |
245 stream_skip(demuxer->stream, len); | |
246 goto loop; | |
247 } | |
248 | |
249 demuxer->filepos = stream_tell(demuxer->stream); | |
3795 | 250 ds_read_packet(ds, demuxer->stream, len, timestamp/90000.0f, |
251 demuxer->filepos, (flags & 0x2) ? 0x10 : 0); | |
3777 | 252 |
253 return 1; | |
254 } | |
255 | |
256 void demux_open_real(demuxer_t* demuxer) | |
257 { | |
258 real_priv_t* priv = demuxer->priv; | |
259 int num_of_headers; | |
260 int i; | |
261 | |
262 stream_skip(demuxer->stream, 4); /* header size */ | |
263 stream_skip(demuxer->stream, 2); | |
264 stream_skip(demuxer->stream, 4); | |
265 num_of_headers = stream_read_dword(demuxer->stream); | |
266 // stream_skip(demuxer->stream, 4); /* number of headers */ | |
267 | |
268 /* parse chunks */ | |
269 for (i = 1; i < num_of_headers; i++) | |
270 { | |
271 int chunk, chunk_size; | |
272 | |
273 chunk = stream_read_dword_le(demuxer->stream); | |
274 chunk_size = stream_read_dword(demuxer->stream); | |
275 | |
276 stream_skip(demuxer->stream, 2); | |
277 | |
278 if (chunk_size < 10) | |
279 goto fail; | |
280 | |
281 printf("Chunk: %.4s (size: %d)\n", | |
282 (char *)&chunk, chunk_size); | |
283 | |
284 switch(chunk) | |
285 { | |
286 case MKTAG('P', 'R', 'O', 'P'): | |
3795 | 287 // printf("Properties chunk\n"); |
3777 | 288 stream_skip(demuxer->stream, 4); /* max bitrate */ |
289 stream_skip(demuxer->stream, 4); /* avg bitrate */ | |
290 stream_skip(demuxer->stream, 4); /* max packet size */ | |
291 stream_skip(demuxer->stream, 4); /* avg packet size */ | |
292 stream_skip(demuxer->stream, 4); /* nb packets */ | |
293 stream_skip(demuxer->stream, 4); /* duration */ | |
294 stream_skip(demuxer->stream, 4); /* preroll */ | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
295 // stream_skip(demuxer->stream, 4); /* index offset */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
296 priv->index_chunk_offset = stream_read_dword(demuxer->stream); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
297 printf("Index chunk offset: 0x%x\n", priv->index_chunk_offset); |
3795 | 298 // stream_skip(demuxer->stream, 4); /* data offset */ |
299 priv->data_chunk_offset = stream_read_dword(demuxer->stream)+10; | |
300 printf("Data chunk offset: 0x%x\n", priv->data_chunk_offset); | |
3777 | 301 stream_skip(demuxer->stream, 2); /* nb streams */ |
3795 | 302 #if 0 |
3777 | 303 stream_skip(demuxer->stream, 2); /* flags */ |
3795 | 304 #else |
305 { | |
306 int flags = stream_read_word(demuxer->stream); | |
307 printf("Flags (%x): ", flags); | |
308 if (flags & 0x1) | |
309 printf("[save allowed] "); | |
310 if (flags & 0x2) | |
311 printf("[perfect play (?)] "); | |
312 if (flags & 0x4) | |
313 printf("[live broadcast] "); | |
314 printf("\n"); | |
315 } | |
316 #endif | |
3777 | 317 break; |
318 case MKTAG('C', 'O', 'N', 'T'): | |
3788 | 319 { |
320 char *buf; | |
321 int len; | |
322 | |
3795 | 323 // printf("Broadcasting informations (title, author, copyright, comment)\n"); |
3788 | 324 |
325 len = stream_read_word(demuxer->stream); | |
326 if (len > 0) | |
327 { | |
328 buf = malloc(len+1); | |
329 stream_read(demuxer->stream, buf, len); | |
330 demux_info_add(demuxer, "name", buf); | |
331 free(buf); | |
332 } | |
333 | |
334 len = stream_read_word(demuxer->stream); | |
335 if (len > 0) | |
336 { | |
337 buf = malloc(len+1); | |
338 stream_read(demuxer->stream, buf, len); | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
339 buf[len] = 0; |
3788 | 340 demux_info_add(demuxer, "author", buf); |
341 free(buf); | |
342 } | |
343 | |
344 len = stream_read_word(demuxer->stream); | |
345 if (len > 0) | |
346 { | |
347 buf = malloc(len+1); | |
348 stream_read(demuxer->stream, buf, len); | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
349 buf[len] = 0; |
3788 | 350 demux_info_add(demuxer, "copyright", buf); |
351 free(buf); | |
352 } | |
353 | |
354 len = stream_read_word(demuxer->stream); | |
355 if (len > 0) | |
356 { | |
357 buf = malloc(len+1); | |
358 stream_read(demuxer->stream, buf, len); | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
359 buf[len] = 0; |
3788 | 360 demux_info_add(demuxer, "comment", buf); |
361 free(buf); | |
362 } | |
363 | |
364 // skip_str(0, demuxer); /* title */ | |
365 // skip_str(0, demuxer); /* author */ | |
366 // skip_str(0, demuxer); /* copyright */ | |
367 // skip_str(0, demuxer); /* comment */ | |
3777 | 368 break; |
3788 | 369 } |
3777 | 370 case MKTAG('M', 'D', 'P', 'R'): |
371 { | |
372 /* new stream */ | |
373 int stream_id; | |
374 int bitrate; | |
375 int codec_data_size; | |
376 int codec_pos; | |
3795 | 377 int tmp; |
3777 | 378 |
379 stream_id = stream_read_word(demuxer->stream); | |
380 printf("Found new stream (id: %d)\n", stream_id); | |
381 | |
382 stream_skip(demuxer->stream, 4); /* max bitrate */ | |
383 bitrate = stream_read_dword(demuxer->stream); /* bitrate */ | |
384 stream_skip(demuxer->stream, 4); /* max packet size */ | |
385 stream_skip(demuxer->stream, 4); /* avg packet size */ | |
386 stream_skip(demuxer->stream, 4); /* start time */ | |
387 stream_skip(demuxer->stream, 4); /* preroll */ | |
388 stream_skip(demuxer->stream, 4); /* duration */ | |
389 | |
390 skip_str(1, demuxer); /* stream description */ | |
391 skip_str(1, demuxer); /* mimetype */ | |
392 | |
393 codec_data_size = stream_read_dword(demuxer->stream); | |
394 codec_pos = stream_tell(demuxer->stream); | |
395 | |
3795 | 396 tmp = stream_read_dword(demuxer->stream); |
397 if (tmp == MKTAG(0xfd, 'a', 'r', '.')) /* audio header */ | |
3777 | 398 { |
399 sh_audio_t *sh = new_sh_audio(demuxer, stream_id); | |
3795 | 400 char buf[128]; /* for codec name */ |
401 int frame_size; | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
402 int version; |
3777 | 403 |
404 printf("Found audio stream!\n"); | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
405 version = stream_read_word(demuxer->stream); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
406 printf("version: %d\n", version); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
407 // stream_skip(demuxer->stream, 2); /* version (4 or 5) */ |
3788 | 408 stream_skip(demuxer->stream, 2); |
409 stream_skip(demuxer->stream, 4); /* .ra4 or .ra5 */ | |
3777 | 410 stream_skip(demuxer->stream, 4); |
3788 | 411 stream_skip(demuxer->stream, 2); /* version (4 or 5) */ |
3777 | 412 stream_skip(demuxer->stream, 4); /* header size */ |
413 stream_skip(demuxer->stream, 2); /* add codec info */ | |
414 stream_skip(demuxer->stream, 4); /* coded frame size */ | |
415 stream_skip(demuxer->stream, 4); | |
416 stream_skip(demuxer->stream, 4); | |
417 stream_skip(demuxer->stream, 4); | |
418 stream_skip(demuxer->stream, 2); /* 1 */ | |
3795 | 419 // stream_skip(demuxer->stream, 2); /* coded frame size */ |
420 frame_size = stream_read_word(demuxer->stream); | |
421 printf("frame_size: %d\n", frame_size); | |
3777 | 422 stream_skip(demuxer->stream, 4); |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
423 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
424 if (version == 5) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
425 stream_skip(demuxer->stream, 6); |
3777 | 426 |
427 sh->samplerate = stream_read_word(demuxer->stream); | |
428 stream_skip(demuxer->stream, 4); | |
429 sh->channels = stream_read_word(demuxer->stream); | |
3877 | 430 printf("samplerate: %d, channels: %d\n", |
431 sh->samplerate, sh->channels); | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
432 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
433 if (version == 5) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
434 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
435 stream_skip(demuxer->stream, 4); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
436 stream_read(demuxer->stream, buf, 4); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
437 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
438 else |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
439 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
440 /* Desc #1 */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
441 skip_str(1, demuxer); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
442 /* Desc #2 */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
443 get_str(1, demuxer, buf, sizeof(buf)); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
444 } |
3777 | 445 |
3795 | 446 tmp = 1; /* supported audio codec */ |
447 switch (MKTAG(buf[0], buf[1], buf[2], buf[3])) | |
448 { | |
449 case MKTAG('d', 'n', 'e', 't'): | |
450 printf("Audio: DNET -> AC3\n"); | |
451 sh->format = 0x2000; | |
452 break; | |
453 case MKTAG('s', 'i', 'p', 'r'): | |
454 printf("Audio: SiproLab's ACELP.net\n"); | |
3788 | 455 sh->format = 0x130; |
3795 | 456 break; |
457 case MKTAG('c', 'o', 'o', 'k'): | |
458 printf("Audio: Real's GeneralCooker (unsupported)\n"); | |
459 tmp = 0; | |
460 break; | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
461 case MKTAG('a', 't', 'r', 'c'): |
3795 | 462 default: |
463 printf("Audio: Unknown (%s)\n", buf); | |
464 tmp = 0; | |
465 sh->format = MKTAG(buf[0], buf[1], buf[2], buf[3]); | |
3777 | 466 } |
467 | |
3795 | 468 if (tmp) |
3777 | 469 { |
3795 | 470 /* Emulate WAVEFORMATEX struct: */ |
471 sh->wf = malloc(sizeof(WAVEFORMATEX)); | |
472 memset(sh->wf, 0, sizeof(WAVEFORMATEX)); | |
473 sh->wf->wFormatTag = sh->format; | |
474 sh->wf->nChannels = sh->channels; | |
475 sh->wf->wBitsPerSample = 16; | |
476 sh->wf->nSamplesPerSec = sh->samplerate; | |
477 sh->wf->nAvgBytesPerSec = bitrate; | |
478 sh->wf->nBlockAlign = frame_size; /* 19 for acelp, pff */ | |
479 sh->wf->cbSize = 0; | |
3788 | 480 |
3795 | 481 /* insert as stream */ |
482 demuxer->audio->sh = sh; | |
483 sh->ds = demuxer->audio; | |
484 demuxer->audio->id = stream_id; | |
3788 | 485 |
3795 | 486 if (priv->last_a_stream+1 < MAX_STREAMS) |
487 { | |
488 priv->a_streams[priv->last_a_stream] = stream_id; | |
489 priv->last_a_stream++; | |
490 } | |
3777 | 491 } |
492 } | |
493 else | |
494 { | |
495 /* video header */ | |
496 sh_video_t *sh = new_sh_video(demuxer, stream_id); | |
497 | |
3795 | 498 tmp = stream_read_dword_le(demuxer->stream); |
499 printf("video: %.4s (%x)\n", (char *)&tmp, tmp); | |
500 if (tmp != MKTAG('V', 'I', 'D', 'O')) | |
3777 | 501 { |
502 mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported video codec\n"); | |
503 goto skip_this_chunk; | |
504 } | |
505 | |
506 sh->format = stream_read_dword_le(demuxer->stream); /* fourcc */ | |
507 printf("video fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format); | |
508 | |
3795 | 509 /* emulate BITMAPINFOHEADER */ |
3777 | 510 sh->bih = malloc(sizeof(BITMAPINFOHEADER)); |
511 memset(sh->bih, 0, sizeof(BITMAPINFOHEADER)); | |
512 sh->bih->biSize = 40; | |
513 sh->disp_w = sh->bih->biWidth = stream_read_word(demuxer->stream); | |
514 sh->disp_h = sh->bih->biHeight = stream_read_word(demuxer->stream); | |
515 sh->bih->biPlanes = 1; | |
516 sh->bih->biBitCount = 24; | |
517 sh->bih->biCompression = sh->format; | |
518 sh->bih->biSizeImage= sh->bih->biWidth*sh->bih->biHeight*3; | |
519 | |
520 sh->fps = stream_read_word(demuxer->stream); | |
521 sh->frametime = 1.0f/sh->fps; | |
522 | |
523 stream_skip(demuxer->stream, 4); | |
524 stream_skip(demuxer->stream, 2); | |
525 stream_skip(demuxer->stream, 4); | |
526 stream_skip(demuxer->stream, 2); | |
527 | |
528 /* h263 hack */ | |
3795 | 529 tmp = stream_read_dword(demuxer->stream); |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
530 printf("H.263 ID: %x\n", tmp); |
3795 | 531 switch (tmp) |
3777 | 532 { |
533 case 0x10000000: | |
534 /* sub id: 0 */ | |
535 /* codec id: rv10 */ | |
536 break; | |
537 case 0x10003000: | |
538 case 0x10003001: | |
539 /* sub id: 3 */ | |
540 /* codec id: rv10 */ | |
3877 | 541 sh->bih->biCompression = sh->format = mmioFOURCC('R', 'V', '1', '3'); |
3777 | 542 break; |
543 case 0x20001000: | |
3788 | 544 case 0x20100001: |
3777 | 545 /* codec id: rv20 */ |
546 break; | |
547 default: | |
548 /* codec id: none */ | |
3795 | 549 printf("unknown id: %x\n", tmp); |
3777 | 550 } |
551 | |
552 /* insert as stream */ | |
553 demuxer->video->sh = sh; | |
554 sh->ds = demuxer->video; | |
555 demuxer->video->id = stream_id; | |
556 if (priv->last_v_stream+1 < MAX_STREAMS) | |
557 { | |
558 priv->v_streams[priv->last_v_stream] = stream_id; | |
559 priv->last_v_stream++; | |
560 } | |
561 } | |
562 | |
563 skip_this_chunk: | |
564 /* skip codec info */ | |
3795 | 565 tmp = stream_tell(demuxer->stream) - codec_pos; |
566 stream_skip(demuxer->stream, codec_data_size - tmp); | |
3777 | 567 break; |
568 } | |
569 case MKTAG('D', 'A', 'T', 'A'): | |
570 goto header_end; | |
3795 | 571 case MKTAG('I', 'N', 'D', 'X'): |
3777 | 572 default: |
573 printf("Unknown chunk: %x\n", chunk); | |
574 stream_skip(demuxer->stream, chunk_size - 10); | |
575 break; | |
576 } | |
577 } | |
578 | |
579 header_end: | |
580 priv->num_of_packets = stream_read_dword(demuxer->stream); | |
581 // stream_skip(demuxer->stream, 4); /* number of packets */ | |
582 stream_skip(demuxer->stream, 4); /* next data header */ | |
583 | |
584 printf("Packets in file: %d\n", priv->num_of_packets); | |
585 | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
586 if (priv->num_of_packets == 0) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
587 priv->num_of_packets = -10; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
588 |
3777 | 589 /* disable seeking */ |
590 demuxer->seekable = 0; | |
591 | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
592 if (priv->index_chunk_offset && (index_mode == 1) || (index_mode == 2)) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
593 parse_index_chunk(demuxer); |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
594 |
3777 | 595 fail: |
596 return; | |
597 } | |
598 | |
599 void demux_close_real(demuxer_t *demuxer) | |
600 { | |
601 real_priv_t* priv = demuxer->priv; | |
602 | |
603 if (priv) | |
604 free(priv); | |
605 | |
606 return; | |
607 } | |
3882
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
608 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
609 #if 0 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
610 /* will complete it later - please upload RV10 samples WITH INDEX CHUNK */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
611 int demux_seek_real(demuxer_t *demuxer, float rel_seek_secs, int flags) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
612 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
613 real_priv_t *priv = demuxer->priv; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
614 demux_stream_t *d_audio = demuxer->audio; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
615 demux_stream_t *d_video = demuxer->video; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
616 sh_audio_t *sh_audio = d_audio->sh; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
617 sh_video_t *sh_video = d_video->sh; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
618 int rel_seek_frames = sh->fps*rel_seek_secs; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
619 int video_chunk_pos = d_video->pos; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
620 int stream_id = 0; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
621 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
622 #if 0 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
623 if (flags & 1) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
624 /* seek absolute */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
625 video_chunk_pos = 0; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
626 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
627 if (flags & 2) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
628 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
629 int total = sh_video->video.dwLength; |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
630 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
631 rel_seek_frames |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
632 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
633 #endif |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
634 |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
635 if (rel_seek_frames > 0) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
636 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
637 /* seek forward */ |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
638 for (i = 0; i < index_table_size[stream_id]; i++) |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
639 { |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
640 if (index_table[stream_id][i] |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
641 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
642 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
643 } |
c5cefeb78c40
added read_index_chunk, fixed audio_header parser for version5
alex
parents:
3877
diff
changeset
|
644 #endif |