Mercurial > mplayer.hg
annotate libmpdemux/demux_viv.c @ 19619:a83e5b8d2e63
Patch from Karolina Lindqvist <karolina.lindqvist@kramnet.se>
"There is a bug in the zoran -vo zr driver, that makes the output garbled
always. It also probably affects the zrmjpeg filter. This patch takes care of
the problem."
Patch tested and OK. And 10l to me, because this bug probably has existed for a
looong time.
author | rik |
---|---|
date | Fri, 01 Sep 2006 18:49:40 +0000 |
parents | 31da49ce5a58 |
children | d7b2fa4c39da |
rev | line source |
---|---|
2687 | 1 // VIVO file parser by A'rpi |
3471 | 2 // VIVO text header parser and audio support by alex |
2687 | 3 |
4 #include <stdio.h> | |
5 #include <stdlib.h> | |
6 #include <unistd.h> | |
2928 | 7 #include <string.h> /* strtok */ |
2687 | 8 |
9 #include "config.h" | |
10 #include "mp_msg.h" | |
11 #include "help_mp.h" | |
12 | |
13 #include "stream.h" | |
14 #include "demuxer.h" | |
15 #include "stheader.h" | |
3471 | 16 #include "bswap.h" |
2687 | 17 |
17343
b07bb7ee7ce4
include the right avcodec.h, consistently with the rest of mplayer
nicodvb
parents:
17226
diff
changeset
|
18 #ifdef USE_LIBAVCODEC_SO |
b07bb7ee7ce4
include the right avcodec.h, consistently with the rest of mplayer
nicodvb
parents:
17226
diff
changeset
|
19 #include <ffmpeg/avcodec.h> |
b07bb7ee7ce4
include the right avcodec.h, consistently with the rest of mplayer
nicodvb
parents:
17226
diff
changeset
|
20 #elif defined(USE_LIBAVCODEC) |
b07bb7ee7ce4
include the right avcodec.h, consistently with the rest of mplayer
nicodvb
parents:
17226
diff
changeset
|
21 #include "libavcodec/avcodec.h" |
17226
255b14c0bc36
malloc padding to avoid access beyond allocated memory
henry
parents:
16175
diff
changeset
|
22 #else |
255b14c0bc36
malloc padding to avoid access beyond allocated memory
henry
parents:
16175
diff
changeset
|
23 #define FF_INPUT_BUFFER_PADDING_SIZE 8 |
255b14c0bc36
malloc padding to avoid access beyond allocated memory
henry
parents:
16175
diff
changeset
|
24 #endif |
255b14c0bc36
malloc padding to avoid access beyond allocated memory
henry
parents:
16175
diff
changeset
|
25 |
3502 | 26 /* parameters ! */ |
3503 | 27 int vivo_param_version = -1; |
3502 | 28 char *vivo_param_acodec = NULL; |
29 int vivo_param_abitrate = -1; | |
30 int vivo_param_samplerate = -1; | |
31 int vivo_param_bytesperblock = -1; | |
32 int vivo_param_width = -1; | |
33 int vivo_param_height = -1; | |
34 int vivo_param_vformat = -1; | |
35 | |
3471 | 36 /* VIVO audio standards from vivog723.acm: |
37 | |
38 G.723: | |
39 FormatTag = 0x111 | |
40 Channels = 1 - mono | |
41 SamplesPerSec = 8000 - 8khz | |
42 AvgBytesPerSec = 800 | |
43 BlockAlign (bytes per block) = 24 | |
44 BitsPerSample = 8 | |
45 | |
46 Siren: | |
47 FormatTag = 0x112 | |
48 Channels = 1 - mono | |
49 SamplesPerSec = 16000 - 16khz | |
50 AvgBytesPerSec = 2000 | |
51 BlockAlign (bytes per block) = 40 | |
52 BitsPerSample = 8 | |
53 */ | |
54 | |
3502 | 55 //enum { VIVO_AUDIO_G723, VIVO_AUDIO_SIREN }; |
56 | |
3471 | 57 #define VIVO_AUDIO_G723 1 |
58 #define VIVO_AUDIO_SIREN 2 | |
2687 | 59 |
60 typedef struct { | |
2784 | 61 /* generic */ |
3113
c0e6a39d2ab7
changed to generate fourcc's like: viv<version> -> viv1,viv2
alex
parents:
3069
diff
changeset
|
62 char version; |
2784 | 63 int supported; |
64 /* info */ | |
65 char *title; | |
66 char *author; | |
67 char *copyright; | |
68 char *producer; | |
69 /* video */ | |
70 float fps; | |
71 int width; | |
72 int height; | |
73 int disp_width; | |
74 int disp_height; | |
75 /* audio */ | |
3471 | 76 int audio_codec; |
77 int audio_bitrate; | |
78 int audio_samplerate; | |
79 int audio_bytesperblock; | |
2687 | 80 } vivo_priv_t; |
81 | |
2784 | 82 /* parse all possible extra headers */ |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
83 /* (audio headers are seperate - mostly with recordtype=3 or 4) */ |
2784 | 84 #define TEXTPARSE_ALL 1 |
85 | |
86 static void vivo_parse_text_header(demuxer_t *demux, int header_len) | |
87 { | |
88 vivo_priv_t* priv = demux->priv; | |
89 char *buf; | |
90 int i; | |
91 char *token; | |
92 char *opt, *param; | |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
93 int parser_in_audio_block = 0; |
2784 | 94 |
95 if (!demux->priv) | |
96 { | |
97 priv = malloc(sizeof(vivo_priv_t)); | |
98 memset(priv, 0, sizeof(vivo_priv_t)); | |
99 demux->priv = priv; | |
100 priv->supported = 0; | |
101 } | |
102 | |
103 buf = malloc(header_len); | |
104 opt = malloc(header_len); | |
105 param = malloc(header_len); | |
106 stream_read(demux->stream, buf, header_len); | |
107 i=0; | |
108 while(i<header_len && buf[i]==0x0D && buf[i+1]==0x0A) i+=2; // skip empty lines | |
109 | |
110 token = strtok(buf, (char *)&("\x0d\x0a")); | |
111 while (token && (header_len>2)) | |
112 { | |
113 header_len -= strlen(token)+2; | |
114 if (sscanf(token, "%[^:]:%[^\n]", opt, param) != 2) | |
115 { | |
17366 | 116 mp_msg(MSGT_DEMUX, MSGL_V, "viv_text_header_parser: bad line: '%s' at ~%#"PRIx64"\n", |
117 token, (int64_t)stream_tell(demux->stream)); | |
2784 | 118 break; |
119 } | |
3471 | 120 mp_dbg(MSGT_DEMUX, MSGL_DBG3, "token: '%s' (%d bytes/%d bytes left)\n", |
2784 | 121 token, strlen(token), header_len); |
3471 | 122 mp_dbg(MSGT_DEMUX, MSGL_DBG3, "token => o: '%s', p: '%s'\n", |
2784 | 123 opt, param); |
124 | |
125 /* checking versions: only v1 or v2 is suitable (or known?:) */ | |
126 if (!strcmp(opt, "Version")) | |
127 { | |
128 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Version: %s\n", param); | |
2928 | 129 if (!strncmp(param, "Vivo/1", 6) || !strncmp(param, "Vivo/2", 6)) |
3113
c0e6a39d2ab7
changed to generate fourcc's like: viv<version> -> viv1,viv2
alex
parents:
3069
diff
changeset
|
130 { |
2784 | 131 priv->supported = 1; |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
132 /* save major version for fourcc */ |
3113
c0e6a39d2ab7
changed to generate fourcc's like: viv<version> -> viv1,viv2
alex
parents:
3069
diff
changeset
|
133 priv->version = param[5]; |
c0e6a39d2ab7
changed to generate fourcc's like: viv<version> -> viv1,viv2
alex
parents:
3069
diff
changeset
|
134 } |
2784 | 135 } |
136 | |
137 /* video specific */ | |
138 if (!strcmp(opt, "FPS")) | |
139 { | |
140 mp_msg(MSGT_DEMUX, MSGL_DBG2, "FPS: %f\n", atof(param)); | |
141 priv->fps = atof(param); | |
142 } | |
143 if (!strcmp(opt, "Width")) | |
144 { | |
145 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Width: %d\n", atoi(param)); | |
146 priv->width = atoi(param); | |
147 } | |
148 if (!strcmp(opt, "Height")) | |
149 { | |
150 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Height: %d\n", atoi(param)); | |
151 priv->height = atoi(param); | |
152 } | |
153 if (!strcmp(opt, "DisplayWidth")) | |
154 { | |
155 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Display Width: %d\n", atoi(param)); | |
156 priv->disp_width = atoi(param); | |
157 } | |
158 if (!strcmp(opt, "DisplayHeight")) | |
159 { | |
160 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Display Height: %d\n", atoi(param)); | |
161 priv->disp_height = atoi(param); | |
162 } | |
163 | |
164 /* audio specific */ | |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
165 if (!strcmp(opt, "RecordType")) |
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
166 { |
3471 | 167 /* no audio recordblock by Vivo/1.00, 3 and 4 by Vivo/2.00 */ |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
168 if ((atoi(param) == 3) || (atoi(param) == 4)) |
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
169 parser_in_audio_block = 1; |
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
170 else |
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
171 parser_in_audio_block = 0; |
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
172 } |
2784 | 173 if (!strcmp(opt, "NominalBitrate")) |
174 { | |
3471 | 175 priv->audio_bitrate = atoi(param); |
176 if (priv->audio_bitrate == 2000) | |
177 priv->audio_codec = VIVO_AUDIO_SIREN; | |
178 if (priv->audio_bitrate == 800) | |
179 priv->audio_codec = VIVO_AUDIO_G723; | |
2784 | 180 } |
181 if (!strcmp(opt, "SamplingFrequency")) | |
182 { | |
3471 | 183 priv->audio_samplerate = atoi(param); |
184 if (priv->audio_samplerate == 16000) | |
185 priv->audio_codec = VIVO_AUDIO_SIREN; | |
186 if (priv->audio_samplerate == 8000) | |
187 priv->audio_codec = VIVO_AUDIO_G723; | |
2784 | 188 } |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
189 if (!strcmp(opt, "Length") && (parser_in_audio_block == 1)) |
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
190 { |
3471 | 191 priv->audio_bytesperblock = atoi(param); /* 24 or 40 kbps */ |
192 if (priv->audio_bytesperblock == 40) | |
193 priv->audio_codec = VIVO_AUDIO_SIREN; | |
194 if (priv->audio_bytesperblock == 24) | |
195 priv->audio_codec = VIVO_AUDIO_G723; | |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
196 } |
2784 | 197 |
198 /* only for displaying some informations about movie*/ | |
199 if (!strcmp(opt, "Title")) | |
200 { | |
3068 | 201 demux_info_add(demux, "name", param); |
3612 | 202 priv->title = strdup(param); |
2784 | 203 } |
204 if (!strcmp(opt, "Author")) | |
205 { | |
3068 | 206 demux_info_add(demux, "author", param); |
3612 | 207 priv->author = strdup(param); |
2784 | 208 } |
209 if (!strcmp(opt, "Copyright")) | |
210 { | |
3068 | 211 demux_info_add(demux, "copyright", param); |
3612 | 212 priv->copyright = strdup(param); |
2784 | 213 } |
214 if (!strcmp(opt, "Producer")) | |
215 { | |
3069 | 216 demux_info_add(demux, "encoder", param); |
3612 | 217 priv->producer = strdup(param); |
2784 | 218 } |
219 | |
220 /* get next token */ | |
221 token = strtok(NULL, (char *)&("\x0d\x0a")); | |
222 } | |
2788 | 223 |
224 if (buf) | |
225 free(buf); | |
226 if (opt) | |
227 free(opt); | |
228 if (param) | |
229 free(param); | |
2784 | 230 } |
231 | |
16175 | 232 static int vivo_check_file(demuxer_t* demuxer){ |
2687 | 233 int i=0; |
234 int len; | |
235 int c; | |
236 unsigned char buf[2048+256]; | |
237 vivo_priv_t* priv; | |
2784 | 238 int orig_pos = stream_tell(demuxer->stream); |
2687 | 239 |
240 mp_msg(MSGT_DEMUX,MSGL_V,"Checking for VIVO\n"); | |
241 | |
242 c=stream_read_char(demuxer->stream); | |
2792 | 243 if(c==-256) return 0; |
2687 | 244 len=0; |
245 while((c=stream_read_char(demuxer->stream))>=0x80){ | |
246 len+=0x80*(c-0x80); | |
247 if(len>1024) return 0; | |
248 } | |
249 len+=c; | |
6139
3898967fcc96
some more output cosmetics, especially for vivo and mov demuxers
arpi
parents:
4407
diff
changeset
|
250 mp_msg(MSGT_DEMUX,MSGL_V,"header block 1 size: %d\n",len); |
2687 | 251 //stream_skip(demuxer->stream,len); |
2928 | 252 |
253 priv=malloc(sizeof(vivo_priv_t)); | |
254 memset(priv,0,sizeof(vivo_priv_t)); | |
255 demuxer->priv=priv; | |
2784 | 256 |
2805 | 257 #if 0 |
2785 | 258 vivo_parse_text_header(demuxer, len); |
2784 | 259 if (priv->supported == 0) |
260 return 0; | |
261 #else | |
2928 | 262 /* this is enought for check (for now) */ |
263 stream_read(demuxer->stream,buf,len); | |
264 buf[len]=0; | |
265 // printf("VIVO header: '%s'\n",buf); | |
266 | |
2687 | 267 // parse header: |
268 i=0; | |
269 while(i<len && buf[i]==0x0D && buf[i+1]==0x0A) i+=2; // skip empty lines | |
2695 | 270 if(strncmp(buf+i,"Version:Vivo/",13)) return 0; // bad version/type! |
2784 | 271 #endif |
2687 | 272 |
2695 | 273 #if 0 |
2687 | 274 c=stream_read_char(demuxer->stream); |
275 if(c) return 0; | |
276 len2=0; | |
277 while((c=stream_read_char(demuxer->stream))>=0x80){ | |
278 len2+=0x80*(c-0x80); | |
279 if(len+len2>2048) return 0; | |
280 } | |
281 len2+=c; | |
6139
3898967fcc96
some more output cosmetics, especially for vivo and mov demuxers
arpi
parents:
4407
diff
changeset
|
282 mp_msg(MSGT_DEMUX,MSGL_V,"header block 2 size: %d\n",len2); |
2687 | 283 stream_skip(demuxer->stream,len2); |
284 // stream_read(demuxer->stream,buf+len,len2); | |
2695 | 285 #endif |
2687 | 286 |
287 // c=stream_read_char(demuxer->stream); | |
288 // printf("first packet: %02X\n",c); | |
289 | |
2784 | 290 stream_seek(demuxer->stream, orig_pos); |
291 | |
16175 | 292 return DEMUXER_TYPE_VIVO; |
2687 | 293 } |
294 | |
3733 | 295 static int audio_pos=0; |
296 static int audio_rate=0; | |
3526 | 297 |
2687 | 298 // return value: |
299 // 0 = EOF or no stream found | |
300 // 1 = successfully read a packet | |
16175 | 301 static int demux_vivo_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){ |
2687 | 302 demux_stream_t *ds=NULL; |
303 int c; | |
304 int len=0; | |
305 int seq; | |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
306 int prefix=0; |
2687 | 307 demux->filepos=stream_tell(demux->stream); |
308 | |
309 c=stream_read_char(demux->stream); | |
2792 | 310 if (c == -256) /* EOF */ |
311 return 0; | |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
312 // printf("c=%x,%02X\n",c,c&0xf0); |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
313 if (c == 0x82) |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
314 { |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
315 /* ok, this works, but pts calculating from header is required! */ |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
316 #warning "Calculate PTS from picture header!" |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
317 prefix = 1; |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
318 c = stream_read_char(demux->stream); |
19075 | 319 mp_msg(MSGT_DEMUX, MSGL_V, "packet 0x82(pos=%u) chunk=%x\n", |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
6139
diff
changeset
|
320 (int)stream_tell(demux->stream), c); |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
321 } |
2687 | 322 switch(c&0xF0){ |
2695 | 323 case 0x00: // header - skip it! |
2784 | 324 { |
2687 | 325 len=stream_read_char(demux->stream); |
2695 | 326 if(len>=0x80) len=0x80*(len-0x80)+stream_read_char(demux->stream); |
19075 | 327 mp_msg(MSGT_DEMUX, MSGL_V, "vivo extra header: %d bytes\n",len); |
2784 | 328 #ifdef TEXTPARSE_ALL |
329 { | |
330 int pos; | |
331 /* also try to parse all headers */ | |
332 pos = stream_tell(demux->stream); | |
333 vivo_parse_text_header(demux, len); | |
334 stream_seek(demux->stream, pos); | |
335 } | |
336 #endif | |
2687 | 337 break; |
2784 | 338 } |
2687 | 339 case 0x10: // video packet |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
340 if (prefix == 1) |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
341 len = stream_read_char(demux->stream); |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
342 else |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
343 len=128; |
2687 | 344 ds=demux->video; |
345 break; | |
346 case 0x20: // video packet | |
347 len=stream_read_char(demux->stream); | |
348 ds=demux->video; | |
349 break; | |
3068 | 350 case 0x30: // audio packet |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
351 if (prefix == 1) |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
352 len = stream_read_char(demux->stream); |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
353 else |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
354 len=40; /* 40kbps */ |
2695 | 355 ds=demux->audio; |
3526 | 356 audio_pos+=len; |
2695 | 357 break; |
2687 | 358 case 0x40: // audio packet |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
359 if (prefix == 1) |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
360 len = stream_read_char(demux->stream); |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
361 else |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
362 len=24; /* 24kbps */ |
2687 | 363 ds=demux->audio; |
3526 | 364 audio_pos+=len; |
2687 | 365 break; |
366 default: | |
17366 | 367 mp_msg(MSGT_DEMUX,MSGL_WARN,"VIVO - unknown ID found: %02X at pos %"PRIu64" contact author!\n", |
368 c, (int64_t)stream_tell(demux->stream)); | |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
369 return 0; |
2687 | 370 } |
3245
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
371 |
1e2a87b7cae8
added support for packet 0x82 (from vivodump.c by arpi)
alex
parents:
3113
diff
changeset
|
372 // printf("chunk=%x, len=%d\n", c, len); |
2687 | 373 |
2695 | 374 if(!ds || ds->id<-1){ |
2687 | 375 if(len) stream_skip(demux->stream,len); |
376 return 1; | |
377 } | |
378 | |
379 seq=c&0x0F; | |
380 | |
381 if(ds->asf_packet){ | |
382 if(ds->asf_seq!=seq){ | |
383 // closed segment, finalize packet: | |
384 ds_add_packet(ds,ds->asf_packet); | |
385 ds->asf_packet=NULL; | |
2695 | 386 // printf("packet!\n"); |
2687 | 387 } else { |
388 // append data to it! | |
389 demux_packet_t* dp=ds->asf_packet; | |
18558
4928dd61f136
Fix potential integer overflows in memory allocation.
rtogni
parents:
17366
diff
changeset
|
390 if(dp->len + len + FF_INPUT_BUFFER_PADDING_SIZE < 0) |
4928dd61f136
Fix potential integer overflows in memory allocation.
rtogni
parents:
17366
diff
changeset
|
391 return 0; |
17226
255b14c0bc36
malloc padding to avoid access beyond allocated memory
henry
parents:
16175
diff
changeset
|
392 dp->buffer=realloc(dp->buffer,dp->len+len+FF_INPUT_BUFFER_PADDING_SIZE); |
255b14c0bc36
malloc padding to avoid access beyond allocated memory
henry
parents:
16175
diff
changeset
|
393 memset(dp->buffer+dp->len+len, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
2687 | 394 //memcpy(dp->buffer+dp->len,data,len); |
395 stream_read(demux->stream,dp->buffer+dp->len,len); | |
396 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len); | |
397 dp->len+=len; | |
398 // we are ready now. | |
2695 | 399 if((c&0xF0)==0x20) --ds->asf_seq; // hack! |
2687 | 400 return 1; |
401 } | |
402 } | |
403 // create new packet: | |
404 { demux_packet_t* dp; | |
405 dp=new_demux_packet(len); | |
406 //memcpy(dp->buffer,data,len); | |
407 stream_read(demux->stream,dp->buffer,len); | |
3526 | 408 dp->pts=audio_rate?((float)audio_pos/(float)audio_rate):0; |
2687 | 409 // dp->flags=keyframe; |
410 // if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur); | |
411 dp->pos=demux->filepos; | |
412 ds->asf_packet=dp; | |
413 ds->asf_seq=seq; | |
414 // we are ready now. | |
415 return 1; | |
416 } | |
417 | |
418 } | |
419 | |
420 static const short h263_format[8][2] = { | |
421 { 0, 0 }, | |
422 { 128, 96 }, | |
423 { 176, 144 }, | |
424 { 352, 288 }, | |
425 { 704, 576 }, | |
426 { 1408, 1152 }, | |
2784 | 427 { 320, 240 } // ??????? or 240x180 (found in vivo2) ? |
2687 | 428 }; |
429 | |
430 static unsigned char* buffer; | |
431 static int bufptr=0; | |
432 static int bitcnt=0; | |
433 static unsigned char buf=0; | |
434 static int format, width, height; | |
435 | |
436 static unsigned int x_get_bits(int n){ | |
437 unsigned int x=0; | |
438 while(n-->0){ | |
439 if(!bitcnt){ | |
440 // fill buff | |
441 buf=buffer[bufptr++]; | |
442 bitcnt=8; | |
443 } | |
444 //x=(x<<1)|(buf&1);buf>>=1; | |
445 x=(x<<1)|(buf>>7);buf<<=1; | |
446 --bitcnt; | |
447 } | |
448 return x; | |
449 } | |
450 | |
451 #define get_bits(xxx,n) x_get_bits(n) | |
452 #define get_bits1(xxx) x_get_bits(1) | |
453 #define skip_bits(xxx,n) x_get_bits(n) | |
454 #define skip_bits1(xxx) x_get_bits(1) | |
455 | |
456 /* most is hardcoded. should extend to handle all h263 streams */ | |
457 static int h263_decode_picture_header(unsigned char *b_ptr) | |
458 { | |
2928 | 459 // int i; |
2695 | 460 |
461 // for(i=0;i<16;i++) printf(" %02X",b_ptr[i]); printf("\n"); | |
2687 | 462 |
463 buffer=b_ptr; | |
464 bufptr=bitcnt=buf=0; | |
465 | |
466 /* picture header */ | |
2695 | 467 if (get_bits(&s->gb, 22) != 0x20){ |
19075 | 468 mp_msg(MSGT_DEMUX, MSGL_FATAL, "bad picture header\n"); |
2687 | 469 return -1; |
2695 | 470 } |
2687 | 471 skip_bits(&s->gb, 8); /* picture timestamp */ |
472 | |
2695 | 473 if (get_bits1(&s->gb) != 1){ |
19075 | 474 mp_msg(MSGT_DEMUX, MSGL_FATAL, "bad marker\n"); |
2687 | 475 return -1; /* marker */ |
2695 | 476 } |
477 if (get_bits1(&s->gb) != 0){ | |
19075 | 478 mp_msg(MSGT_DEMUX, MSGL_FATAL, "bad h263 id\n"); |
2687 | 479 return -1; /* h263 id */ |
2695 | 480 } |
2687 | 481 skip_bits1(&s->gb); /* split screen off */ |
482 skip_bits1(&s->gb); /* camera off */ | |
483 skip_bits1(&s->gb); /* freeze picture release off */ | |
484 | |
485 format = get_bits(&s->gb, 3); | |
486 | |
487 if (format != 7) { | |
19075 | 488 mp_msg(MSGT_DEMUX, MSGL_V, "h263_plus = 0 format = %d\n", format); |
2687 | 489 /* H.263v1 */ |
490 width = h263_format[format][0]; | |
491 height = h263_format[format][1]; | |
19075 | 492 mp_msg(MSGT_DEMUX, MSGL_V, "%d x %d\n", width, height); |
2695 | 493 // if (!width) return -1; |
2687 | 494 |
19075 | 495 mp_msg(MSGT_DEMUX, MSGL_V, "pict_type=%d\n", get_bits1(&s->gb)); |
496 mp_msg(MSGT_DEMUX, MSGL_V, "unrestricted_mv=%d\n", get_bits1(&s->gb)); | |
2687 | 497 #if 1 |
19075 | 498 mp_msg(MSGT_DEMUX, MSGL_V, "SAC: %d\n", get_bits1(&s->gb)); |
499 mp_msg(MSGT_DEMUX, MSGL_V, "advanced prediction mode: %d\n", get_bits1(&s->gb)); | |
500 mp_msg(MSGT_DEMUX, MSGL_V, "PB frame: %d\n", get_bits1(&s->gb)); | |
2687 | 501 #else |
502 if (get_bits1(&s->gb) != 0) | |
503 return -1; /* SAC: off */ | |
504 if (get_bits1(&s->gb) != 0) | |
505 return -1; /* advanced prediction mode: off */ | |
506 if (get_bits1(&s->gb) != 0) | |
507 return -1; /* not PB frame */ | |
508 #endif | |
19075 | 509 mp_msg(MSGT_DEMUX, MSGL_V, "qscale=%d\n", get_bits(&s->gb, 5)); |
2687 | 510 skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */ |
511 } else { | |
19075 | 512 mp_msg(MSGT_DEMUX, MSGL_V, "h263_plus = 1\n"); |
2687 | 513 /* H.263v2 */ |
2695 | 514 if (get_bits(&s->gb, 3) != 1){ |
19075 | 515 mp_msg(MSGT_DEMUX, MSGL_FATAL, "H.263v2 A error\n"); |
2687 | 516 return -1; |
2695 | 517 } |
518 if (get_bits(&s->gb, 3) != 6){ /* custom source format */ | |
19075 | 519 mp_msg(MSGT_DEMUX, MSGL_FATAL, "custom source format\n"); |
2687 | 520 return -1; |
2695 | 521 } |
2687 | 522 skip_bits(&s->gb, 12); |
523 skip_bits(&s->gb, 3); | |
19075 | 524 mp_msg(MSGT_DEMUX, MSGL_V, "pict_type=%d\n", get_bits(&s->gb, 3) + 1); |
2687 | 525 // if (s->pict_type != I_TYPE && |
526 // s->pict_type != P_TYPE) | |
527 // return -1; | |
528 skip_bits(&s->gb, 7); | |
529 skip_bits(&s->gb, 4); /* aspect ratio */ | |
530 width = (get_bits(&s->gb, 9) + 1) * 4; | |
531 skip_bits1(&s->gb); | |
532 height = get_bits(&s->gb, 9) * 4; | |
19075 | 533 mp_msg(MSGT_DEMUX, MSGL_V, "%d x %d\n", width, height); |
2695 | 534 //if (height == 0) |
535 // return -1; | |
19075 | 536 mp_msg(MSGT_DEMUX, MSGL_V, "qscale=%d\n", get_bits(&s->gb, 5)); |
2687 | 537 } |
538 | |
539 /* PEI */ | |
540 while (get_bits1(&s->gb) != 0) { | |
541 skip_bits(&s->gb, 8); | |
542 } | |
543 // s->f_code = 1; | |
544 // s->width = width; | |
545 // s->height = height; | |
546 return 0; | |
547 } | |
548 | |
549 | |
2695 | 550 |
16175 | 551 static demuxer_t* demux_open_vivo(demuxer_t* demuxer){ |
2687 | 552 vivo_priv_t* priv=demuxer->priv; |
553 | |
554 if(!ds_fill_buffer(demuxer->video)){ | |
555 mp_msg(MSGT_DEMUX,MSGL_ERR,"VIVO: " MSGTR_MissingVideoStreamBug); | |
16175 | 556 return NULL; |
2687 | 557 } |
3526 | 558 |
559 audio_pos=0; | |
2687 | 560 |
561 h263_decode_picture_header(demuxer->video->buffer); | |
562 | |
3503 | 563 if (vivo_param_version != -1) |
564 priv->version = '0' + vivo_param_version; | |
2687 | 565 |
566 { sh_video_t* sh=new_sh_video(demuxer,0); | |
3113
c0e6a39d2ab7
changed to generate fourcc's like: viv<version> -> viv1,viv2
alex
parents:
3069
diff
changeset
|
567 |
c0e6a39d2ab7
changed to generate fourcc's like: viv<version> -> viv1,viv2
alex
parents:
3069
diff
changeset
|
568 /* viv1, viv2 (for better codecs.conf) */ |
c0e6a39d2ab7
changed to generate fourcc's like: viv<version> -> viv1,viv2
alex
parents:
3069
diff
changeset
|
569 sh->format = mmioFOURCC('v', 'i', 'v', priv->version); |
2784 | 570 if(!sh->fps) |
2928 | 571 { |
2784 | 572 if (priv->fps) |
573 sh->fps=priv->fps; | |
574 else | |
575 sh->fps=15.0f; | |
2928 | 576 } |
2687 | 577 sh->frametime=1.0f/sh->fps; |
2805 | 578 |
3502 | 579 /* XXX: FIXME: can't scale image. */ |
580 /* hotfix to disable: */ | |
2805 | 581 priv->disp_width = priv->width; |
582 priv->disp_height = priv->height; | |
583 | |
3502 | 584 if (vivo_param_width != -1) |
585 priv->disp_width = priv->width = vivo_param_width; | |
586 | |
587 if (vivo_param_height != -1) | |
588 priv->disp_height = priv->height = vivo_param_height; | |
589 | |
590 if (vivo_param_vformat != -1) | |
591 { | |
592 priv->disp_width = priv->width = h263_format[vivo_param_vformat][0]; | |
593 priv->disp_height = priv->height = h263_format[vivo_param_vformat][1]; | |
594 } | |
595 | |
2784 | 596 if (priv->disp_width) |
597 sh->disp_w = priv->disp_width; | |
598 else | |
599 sh->disp_w = width; | |
600 if (priv->disp_height) | |
601 sh->disp_h = priv->disp_height; | |
602 else | |
603 sh->disp_h = height; | |
2687 | 604 |
605 // emulate BITMAPINFOHEADER: | |
606 sh->bih=malloc(sizeof(BITMAPINFOHEADER)); | |
607 memset(sh->bih,0,sizeof(BITMAPINFOHEADER)); | |
608 sh->bih->biSize=40; | |
2784 | 609 if (priv->width) |
610 sh->bih->biWidth = priv->width; | |
611 else | |
612 sh->bih->biWidth = width; | |
613 if (priv->height) | |
614 sh->bih->biHeight = priv->height; | |
615 else | |
616 sh->bih->biHeight = height; | |
2687 | 617 sh->bih->biPlanes=1; |
618 sh->bih->biBitCount=24; | |
619 sh->bih->biCompression=sh->format; | |
620 sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight*3; | |
3502 | 621 |
622 /* insert as stream */ | |
623 demuxer->video->sh=sh; | |
624 sh->ds=demuxer->video; | |
2687 | 625 demuxer->video->id=0; |
2928 | 626 |
3502 | 627 /* disable seeking */ |
2928 | 628 demuxer->seekable = 0; |
2788 | 629 |
19075 | 630 mp_msg(MSGT_DEMUX,MSGL_V,"VIVO Video stream %d size: display: %dx%d, codec: %ux%u\n", |
2788 | 631 demuxer->video->id, sh->disp_w, sh->disp_h, sh->bih->biWidth, |
632 sh->bih->biHeight); | |
2687 | 633 } |
634 | |
3502 | 635 /* AUDIO init */ |
636 if (demuxer->audio->id >= -1){ | |
2687 | 637 if(!ds_fill_buffer(demuxer->audio)){ |
638 mp_msg(MSGT_DEMUX,MSGL_ERR,"VIVO: " MSGTR_MissingAudioStream); | |
639 } else | |
640 { sh_audio_t* sh=new_sh_audio(demuxer,1); | |
2788 | 641 |
3502 | 642 /* Select audio codec */ |
3471 | 643 if (priv->audio_codec == 0) |
644 { | |
645 if (priv->version == '2') | |
646 priv->audio_codec = VIVO_AUDIO_SIREN; | |
647 else | |
648 priv->audio_codec = VIVO_AUDIO_G723; | |
649 } | |
3502 | 650 if (vivo_param_acodec != NULL) |
651 { | |
652 if (!strcasecmp(vivo_param_acodec, "g723")) | |
653 priv->audio_codec = VIVO_AUDIO_G723; | |
654 if (!strcasecmp(vivo_param_acodec, "siren")) | |
655 priv->audio_codec = VIVO_AUDIO_SIREN; | |
656 } | |
3471 | 657 |
3502 | 658 if (priv->audio_codec == VIVO_AUDIO_G723) |
659 sh->format = 0x111; | |
9955
d6be831a5f9a
fixed 2 10l-s (bug found in the spring cleanup patch by Raindel Shachar
alex
parents:
8254
diff
changeset
|
660 else if (priv->audio_codec == VIVO_AUDIO_SIREN) |
3502 | 661 sh->format = 0x112; |
9955
d6be831a5f9a
fixed 2 10l-s (bug found in the spring cleanup patch by Raindel Shachar
alex
parents:
8254
diff
changeset
|
662 else |
3502 | 663 { |
664 mp_msg(MSGT_DEMUX, MSGL_ERR, "VIVO: Not support audio codec (%d)\n", | |
665 priv->audio_codec); | |
18708
9e2b300db17b
Change free_sh_audio() to take demuxer and stream id as parameters
uau
parents:
18558
diff
changeset
|
666 free_sh_audio(demuxer, 1); |
3502 | 667 goto nosound; |
668 } | |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
669 |
2687 | 670 // Emulate WAVEFORMATEX struct: |
671 sh->wf=malloc(sizeof(WAVEFORMATEX)); | |
672 memset(sh->wf,0,sizeof(WAVEFORMATEX)); | |
3439
192449c155c7
fixed Waveformatheader emu and added vivo1/2 audio detection
alex
parents:
3245
diff
changeset
|
673 sh->wf->wFormatTag=sh->format; |
3502 | 674 sh->wf->nChannels=1; /* 1 channels for both Siren and G.723 */ |
675 | |
676 /* Set bits per sample */ | |
3471 | 677 if (priv->audio_codec == VIVO_AUDIO_SIREN) |
3502 | 678 sh->wf->wBitsPerSample = 16; |
3471 | 679 else |
3502 | 680 if (priv->audio_codec == VIVO_AUDIO_G723) |
681 sh->wf->wBitsPerSample = 8; | |
682 | |
683 /* Set sampling rate */ | |
684 if (priv->audio_samplerate) /* got from header */ | |
685 sh->wf->nSamplesPerSec = priv->audio_samplerate; | |
3471 | 686 else |
687 { | |
688 if (priv->audio_codec == VIVO_AUDIO_SIREN) | |
3502 | 689 sh->wf->nSamplesPerSec = 16000; |
690 if (priv->audio_codec == VIVO_AUDIO_G723) | |
691 sh->wf->nSamplesPerSec = 8000; | |
3471 | 692 } |
3502 | 693 if (vivo_param_samplerate != -1) |
694 sh->wf->nSamplesPerSec = vivo_param_samplerate; | |
695 | |
696 /* Set audio bitrate */ | |
697 if (priv->audio_bitrate) /* got from header */ | |
698 sh->wf->nAvgBytesPerSec = priv->audio_bitrate; | |
2784 | 699 else |
3471 | 700 { |
701 if (priv->audio_codec == VIVO_AUDIO_SIREN) | |
702 sh->wf->nAvgBytesPerSec = 2000; | |
3502 | 703 if (priv->audio_codec == VIVO_AUDIO_G723) |
3471 | 704 sh->wf->nAvgBytesPerSec = 800; |
705 } | |
3502 | 706 if (vivo_param_abitrate != -1) |
707 sh->wf->nAvgBytesPerSec = vivo_param_abitrate; | |
3526 | 708 audio_rate=sh->wf->nAvgBytesPerSec; |
3502 | 709 |
3471 | 710 if (!priv->audio_bytesperblock) |
711 { | |
712 if (priv->audio_codec == VIVO_AUDIO_SIREN) | |
3502 | 713 sh->wf->nBlockAlign = 40; |
714 if (priv->audio_codec == VIVO_AUDIO_G723) | |
715 sh->wf->nBlockAlign = 24; | |
3471 | 716 } |
717 else | |
3502 | 718 sh->wf->nBlockAlign = priv->audio_bytesperblock; |
719 if (vivo_param_bytesperblock != -1) | |
720 sh->wf->nBlockAlign = vivo_param_bytesperblock; | |
721 | |
8254
772d6d27fd66
warning patch by (Dominik Mierzejewski <dominik at rangers dot eu dot org>)
michael
parents:
7472
diff
changeset
|
722 /*sound_ok:*/ |
3502 | 723 /* insert as stream */ |
724 demuxer->audio->sh=sh; | |
725 sh->ds=demuxer->audio; | |
2687 | 726 demuxer->audio->id=1; |
3502 | 727 nosound: |
16175 | 728 return demuxer; |
2687 | 729 } |
2695 | 730 } |
16175 | 731 return demuxer; |
732 } | |
2687 | 733 |
16175 | 734 static void demux_close_vivo(demuxer_t *demuxer) |
2788 | 735 { |
736 vivo_priv_t* priv=demuxer->priv; | |
2809 | 737 |
738 if (priv) { | |
739 if (priv->title) | |
740 free(priv->title); | |
741 if (priv->author) | |
742 free(priv->author); | |
743 if (priv->copyright) | |
744 free(priv->copyright); | |
745 if (priv->producer) | |
746 free(priv->producer); | |
2788 | 747 free(priv); |
2809 | 748 } |
2788 | 749 return; |
750 } | |
16175 | 751 |
752 | |
753 demuxer_desc_t demuxer_desc_vivo = { | |
754 "Vivo demuxer", | |
755 "vivo", | |
756 "VIVO", | |
757 "A'rpi, Alex Beregszasi", | |
758 "", | |
759 DEMUXER_TYPE_VIVO, | |
760 0, // unsafe autodetect | |
761 vivo_check_file, | |
762 demux_vivo_fill_buffer, | |
763 demux_open_vivo, | |
764 demux_close_vivo, | |
765 NULL, | |
766 NULL | |
767 }; |