comparison libmpdemux/demux_real.c @ 3777:026ccd3dc489

added real demuxer
author alex
date Wed, 26 Dec 2001 22:57:51 +0000
parents
children d554b5b33d76
comparison
equal deleted inserted replaced
3776:a90d45d7bde6 3777:026ccd3dc489
1 /*
2 Real parser & demuxer
3
4 (C) Alex Beregszaszi <alex@naxine.org>
5
6 Based on FFmpeg's libav/rm.c.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12
13 #include "config.h"
14 #include "mp_msg.h"
15 #include "help_mp.h"
16
17 #include "stream.h"
18 #include "demuxer.h"
19 #include "stheader.h"
20 #include "bswap.h"
21
22 #define MKTAG(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))
23
24 #define MAX_STREAMS 10
25
26 typedef struct {
27 int num_of_packets;
28 int last_a_stream;
29 int a_streams[MAX_STREAMS];
30 int last_v_stream;
31 int v_streams[MAX_STREAMS];
32 } real_priv_t;
33
34 static void get_str(int isbyte, demuxer_t *demuxer, char *buf, int buf_size)
35 {
36 int len, i;
37 char *q;
38
39 if (isbyte)
40 len = stream_read_char(demuxer->stream);
41 else
42 len = stream_read_word(demuxer->stream);
43 #if 1
44 q = buf;
45 for (i = 0; i < len; i++)
46 if (i < (buf_size - 1))
47 *q++ = stream_read_char(demuxer->stream);
48 *q = 0;
49 #else
50 stream_read(demuxer->stream, buf, buf_size);
51 #endif
52 }
53
54 static void skip_str(int isbyte, demuxer_t *demuxer)
55 {
56 int len;
57
58 if (isbyte)
59 len = stream_read_char(demuxer->stream);
60 else
61 len = stream_read_word(demuxer->stream);
62
63 stream_skip(demuxer->stream, len);
64
65 printf("skip_str: %d bytes skipped\n", len);
66 }
67
68 int real_check_file(demuxer_t* demuxer){
69 real_priv_t *priv;
70 int c;
71
72 mp_msg(MSGT_DEMUX,MSGL_V,"Checking for REAL\n");
73
74 c = stream_read_dword_le(demuxer->stream);
75 if (c == -256)
76 return 0; /* EOF */
77 if (c != MKTAG('.', 'R', 'M', 'F'))
78 return 0; /* bad magic */
79
80 priv = malloc(sizeof(real_priv_t));
81 memset(priv, 0, sizeof(real_priv_t));
82 demuxer->priv = priv;
83
84 return 1;
85 }
86
87 // return value:
88 // 0 = EOF or no stream found
89 // 1 = successfully read a packet
90 int demux_real_fill_buffer(demuxer_t *demuxer)
91 {
92 real_priv_t *priv = demuxer->priv;
93 demux_stream_t *ds = NULL;
94 int len;
95 int timestamp;
96 int stream_id;
97 int i;
98
99 // printf("num_of_packets: %d\n", priv->num_of_packets);
100
101 loop:
102 if (priv->num_of_packets == 0)
103 return 0; /* EOF */
104 stream_skip(demuxer->stream, 2);
105 len = stream_read_word(demuxer->stream);
106 if (len == -256) /* EOF */
107 return 0;
108 if (len < 12)
109 {
110 printf("bad packet len (%d)\n", len);
111 stream_skip(demuxer->stream, len);
112 goto loop;
113 // return 0; /* bad packet */
114 }
115 stream_id = stream_read_word(demuxer->stream);
116 timestamp = stream_read_dword(demuxer->stream);
117
118 // printf("packet: len: %d, stream_id: %d, timestamp: %d\n",
119 // len, stream_id, timestamp);
120
121 stream_skip(demuxer->stream, 1); /* reserved */
122 stream_skip(demuxer->stream, 1); /* flags */
123
124 priv->num_of_packets--;
125 len -= 12;
126
127 /* check if stream_id is audio stream */
128 for (i = 0; i < priv->last_a_stream; i++)
129 {
130 if (priv->a_streams[i] == stream_id)
131 {
132 // printf("packet is audio (id: %d)\n", stream_id);
133 ds = demuxer->audio; /* FIXME */
134 break;
135 }
136 }
137 /* check if stream_id is video stream */
138 for (i = 0; i < priv->last_v_stream; i++)
139 {
140 if (priv->v_streams[i] == stream_id)
141 {
142 // printf("packet is video (id: %d)\n", stream_id);
143 ds = demuxer->video; /* FIXME */
144 break;
145 }
146 }
147
148 /* id not found */
149 if (ds == NULL)
150 {
151 printf("unknown stream id (%d)\n", stream_id);
152 stream_skip(demuxer->stream, len);
153 goto loop;
154 }
155
156 demuxer->filepos = stream_tell(demuxer->stream);
157 ds_read_packet(ds, demuxer->stream, len, timestamp/90000.0f, demuxer->filepos, 0);
158
159 return 1;
160 }
161
162 void demux_open_real(demuxer_t* demuxer)
163 {
164 real_priv_t* priv = demuxer->priv;
165 int num_of_headers;
166 int i;
167
168 stream_skip(demuxer->stream, 4); /* header size */
169 stream_skip(demuxer->stream, 2);
170 stream_skip(demuxer->stream, 4);
171 num_of_headers = stream_read_dword(demuxer->stream);
172 // stream_skip(demuxer->stream, 4); /* number of headers */
173
174 /* parse chunks */
175 for (i = 1; i < num_of_headers; i++)
176 {
177 int chunk, chunk_size;
178
179 chunk = stream_read_dword_le(demuxer->stream);
180 chunk_size = stream_read_dword(demuxer->stream);
181
182 stream_skip(demuxer->stream, 2);
183
184 if (chunk_size < 10)
185 goto fail;
186
187 printf("Chunk: %.4s (size: %d)\n",
188 (char *)&chunk, chunk_size);
189
190 switch(chunk)
191 {
192 case MKTAG('P', 'R', 'O', 'P'):
193 printf("Properties chunk\n");
194 stream_skip(demuxer->stream, 4); /* max bitrate */
195 stream_skip(demuxer->stream, 4); /* avg bitrate */
196 stream_skip(demuxer->stream, 4); /* max packet size */
197 stream_skip(demuxer->stream, 4); /* avg packet size */
198 stream_skip(demuxer->stream, 4); /* nb packets */
199 stream_skip(demuxer->stream, 4); /* duration */
200 stream_skip(demuxer->stream, 4); /* preroll */
201 stream_skip(demuxer->stream, 4); /* index offset */
202 stream_skip(demuxer->stream, 4); /* data offset */
203 stream_skip(demuxer->stream, 2); /* nb streams */
204 stream_skip(demuxer->stream, 2); /* flags */
205 break;
206 case MKTAG('C', 'O', 'N', 'T'):
207 printf("Broadcasting informations (title, author, copyright, comment)\n");
208 skip_str(0, demuxer); /* title */
209 skip_str(0, demuxer); /* author */
210 skip_str(0, demuxer); /* copyright */
211 skip_str(0, demuxer); /* comment */
212 break;
213 case MKTAG('M', 'D', 'P', 'R'):
214 {
215 /* new stream */
216 int stream_id;
217 int bitrate;
218 int codec_data_size;
219 int codec_pos;
220 int v;
221
222 stream_id = stream_read_word(demuxer->stream);
223 printf("Found new stream (id: %d)\n", stream_id);
224
225 stream_skip(demuxer->stream, 4); /* max bitrate */
226 bitrate = stream_read_dword(demuxer->stream); /* bitrate */
227 stream_skip(demuxer->stream, 4); /* max packet size */
228 stream_skip(demuxer->stream, 4); /* avg packet size */
229 stream_skip(demuxer->stream, 4); /* start time */
230 stream_skip(demuxer->stream, 4); /* preroll */
231 stream_skip(demuxer->stream, 4); /* duration */
232
233 skip_str(1, demuxer); /* stream description */
234 skip_str(1, demuxer); /* mimetype */
235
236 codec_data_size = stream_read_dword(demuxer->stream);
237 codec_pos = stream_tell(demuxer->stream);
238
239 v = stream_read_dword(demuxer->stream);
240 if (v == MKTAG(0xfd, 'a', 'r', '.')) /* audio header */
241 {
242 sh_audio_t *sh = new_sh_audio(demuxer, stream_id);
243
244 printf("Found audio stream!\n");
245 stream_skip(demuxer->stream, 4); /* version */
246 stream_skip(demuxer->stream, 4); /* .ra4 */
247 stream_skip(demuxer->stream, 4);
248 stream_skip(demuxer->stream, 2);
249 stream_skip(demuxer->stream, 4); /* header size */
250 stream_skip(demuxer->stream, 2); /* add codec info */
251 stream_skip(demuxer->stream, 4); /* coded frame size */
252 stream_skip(demuxer->stream, 4);
253 stream_skip(demuxer->stream, 4);
254 stream_skip(demuxer->stream, 4);
255 stream_skip(demuxer->stream, 2); /* 1 */
256 stream_skip(demuxer->stream, 2); /* coded frame size */
257 stream_skip(demuxer->stream, 4);
258
259 sh->samplerate = stream_read_word(demuxer->stream);
260 stream_skip(demuxer->stream, 4);
261 sh->channels = stream_read_word(demuxer->stream);
262
263 {
264 char buf[128];
265
266 get_str(1, demuxer, buf, sizeof(buf));
267 get_str(1, demuxer, buf, sizeof(buf));
268
269 v = 0; /* not supported audio codec */
270 if (!strcmp(buf, "dnet"))
271 {
272 printf("Found AC3 audio\n");
273 sh->format = 0x2000; /* ac3 */
274 v = 1;
275 }
276 }
277 // skip_str(1, demuxer); /* desc */
278 // skip_str(1, demuxer); /* desc */
279
280 /* the audio codec name is stored in desc */
281 /* available codecs: DNET -> ac3 */
282 // sh->format = 0x2000; /* ac3 */
283
284 if (v)
285 {
286 printf("Audio codec: 0x%x\n", sh->format);
287 /* insert as stream */
288 demuxer->audio->sh = sh;
289 sh->ds = demuxer->audio;
290 demuxer->audio->id = stream_id;
291
292 if (priv->last_a_stream+1 < MAX_STREAMS)
293 {
294 priv->a_streams[priv->last_a_stream] = stream_id;
295 priv->last_a_stream++;
296 }
297 }
298 }
299 else
300 {
301 /* video header */
302 sh_video_t *sh = new_sh_video(demuxer, stream_id);
303
304 v = stream_read_dword_le(demuxer->stream);
305 printf("video: %.4s (%x)\n", (char *)&v, v);
306 if (v != MKTAG('V', 'I', 'D', 'O'))
307 {
308 mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported video codec\n");
309 goto skip_this_chunk;
310 }
311
312 sh->format = stream_read_dword_le(demuxer->stream); /* fourcc */
313 printf("video fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format);
314
315 // emulate BITMAPINFOHEADER:
316 sh->bih = malloc(sizeof(BITMAPINFOHEADER));
317 memset(sh->bih, 0, sizeof(BITMAPINFOHEADER));
318 sh->bih->biSize = 40;
319 sh->disp_w = sh->bih->biWidth = stream_read_word(demuxer->stream);
320 sh->disp_h = sh->bih->biHeight = stream_read_word(demuxer->stream);
321 sh->bih->biPlanes = 1;
322 sh->bih->biBitCount = 24;
323 sh->bih->biCompression = sh->format;
324 sh->bih->biSizeImage= sh->bih->biWidth*sh->bih->biHeight*3;
325
326 sh->fps = stream_read_word(demuxer->stream);
327 sh->frametime = 1.0f/sh->fps;
328
329 stream_skip(demuxer->stream, 4);
330 stream_skip(demuxer->stream, 2);
331 stream_skip(demuxer->stream, 4);
332 stream_skip(demuxer->stream, 2);
333
334 /* h263 hack */
335 v = stream_read_dword(demuxer->stream);
336 switch (v)
337 {
338 case 0x10000000:
339 /* sub id: 0 */
340 /* codec id: rv10 */
341 break;
342 case 0x10003000:
343 case 0x10003001:
344 /* sub id: 3 */
345 /* codec id: rv10 */
346 break;
347 case 0x20001000:
348 /* codec id: rv20 */
349 break;
350 default:
351 /* codec id: none */
352 }
353
354 /* insert as stream */
355 demuxer->video->sh = sh;
356 sh->ds = demuxer->video;
357 demuxer->video->id = stream_id;
358 if (priv->last_v_stream+1 < MAX_STREAMS)
359 {
360 priv->v_streams[priv->last_v_stream] = stream_id;
361 priv->last_v_stream++;
362 }
363 }
364
365 skip_this_chunk:
366 /* skip codec info */
367 v = stream_tell(demuxer->stream) - codec_pos;
368 stream_skip(demuxer->stream, codec_data_size - v);
369 break;
370 }
371 case MKTAG('D', 'A', 'T', 'A'):
372 goto header_end;
373 default:
374 printf("Unknown chunk: %x\n", chunk);
375 stream_skip(demuxer->stream, chunk_size - 10);
376 break;
377 }
378 }
379
380 header_end:
381 priv->num_of_packets = stream_read_dword(demuxer->stream);
382 // stream_skip(demuxer->stream, 4); /* number of packets */
383 stream_skip(demuxer->stream, 4); /* next data header */
384
385 printf("Packets in file: %d\n", priv->num_of_packets);
386
387 /* disable seeking */
388 demuxer->seekable = 0;
389
390 fail:
391 return;
392 }
393
394 void demux_close_real(demuxer_t *demuxer)
395 {
396 real_priv_t* priv = demuxer->priv;
397
398 if (priv)
399 free(priv);
400
401 return;
402 }