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