1 // VIVO file parser by A'rpi
2 // VIVO text header parser and audio support by alex
7 #include <string.h> /* strtok */
19 int vivo_param_version
= -1;
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;
28 /* VIVO audio standards from vivog723.acm:
33 SamplesPerSec = 8000 - 8khz
35 BlockAlign (bytes per block) = 24
41 SamplesPerSec = 16000 - 16khz
43 BlockAlign (bytes per block) = 40
47 //enum { VIVO_AUDIO_G723, VIVO_AUDIO_SIREN };
49 #define VIVO_AUDIO_G723 1
50 #define VIVO_AUDIO_SIREN 2
71 int audio_bytesperblock
;
74 /* parse all possible extra headers */
75 /* (audio headers are seperate - mostly with recordtype=3 or 4) */
76 #define TEXTPARSE_ALL 1
78 static void vivo_parse_text_header(demuxer_t
*demux
, int header_len
)
80 vivo_priv_t
* priv
= demux
->priv
;
85 int parser_in_audio_block
= 0;
89 priv
= malloc(sizeof(vivo_priv_t
));
90 memset(priv
, 0, sizeof(vivo_priv_t
));
95 buf
= malloc(header_len
);
96 opt
= malloc(header_len
);
97 param
= malloc(header_len
);
98 stream_read(demux
->stream
, buf
, header_len
);
100 while(i
<header_len
&& buf
[i
]==0x0D && buf
[i
+1]==0x0A) i
+=2; // skip empty lines
102 token
= strtok(buf
, (char *)&("\x0d\x0a"));
103 while (token
&& (header_len
>2))
105 header_len
-= strlen(token
)+2;
106 if (sscanf(token
, "%[^:]:%[^\n]", opt
, param
) != 2)
108 mp_msg(MSGT_DEMUX
, MSGL_V
, "viv_text_header_parser: bad line: '%s' at ~%p\n",
109 token
, stream_tell(demux
->stream
));
112 mp_dbg(MSGT_DEMUX
, MSGL_DBG3
, "token: '%s' (%d bytes/%d bytes left)\n",
113 token
, strlen(token
), header_len
);
114 mp_dbg(MSGT_DEMUX
, MSGL_DBG3
, "token => o: '%s', p: '%s'\n",
117 /* checking versions: only v1 or v2 is suitable (or known?:) */
118 if (!strcmp(opt
, "Version"))
120 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Version: %s\n", param
);
121 if (!strncmp(param
, "Vivo/1", 6) || !strncmp(param
, "Vivo/2", 6))
124 /* save major version for fourcc */
125 priv
->version
= param
[5];
130 if (!strcmp(opt
, "FPS"))
132 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "FPS: %f\n", atof(param
));
133 priv
->fps
= atof(param
);
135 if (!strcmp(opt
, "Width"))
137 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Width: %d\n", atoi(param
));
138 priv
->width
= atoi(param
);
140 if (!strcmp(opt
, "Height"))
142 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Height: %d\n", atoi(param
));
143 priv
->height
= atoi(param
);
145 if (!strcmp(opt
, "DisplayWidth"))
147 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Display Width: %d\n", atoi(param
));
148 priv
->disp_width
= atoi(param
);
150 if (!strcmp(opt
, "DisplayHeight"))
152 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Display Height: %d\n", atoi(param
));
153 priv
->disp_height
= atoi(param
);
157 if (!strcmp(opt
, "RecordType"))
159 /* no audio recordblock by Vivo/1.00, 3 and 4 by Vivo/2.00 */
160 if ((atoi(param
) == 3) || (atoi(param
) == 4))
161 parser_in_audio_block
= 1;
163 parser_in_audio_block
= 0;
165 if (!strcmp(opt
, "NominalBitrate"))
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
;
173 if (!strcmp(opt
, "SamplingFrequency"))
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
;
181 if (!strcmp(opt
, "Length") && (parser_in_audio_block
== 1))
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
;
190 /* only for displaying some informations about movie*/
191 if (!strcmp(opt
, "Title"))
193 demux_info_add(demux
, "name", param
);
194 priv
->title
= strdup(param
);
196 if (!strcmp(opt
, "Author"))
198 demux_info_add(demux
, "author", param
);
199 priv
->author
= strdup(param
);
201 if (!strcmp(opt
, "Copyright"))
203 demux_info_add(demux
, "copyright", param
);
204 priv
->copyright
= strdup(param
);
206 if (!strcmp(opt
, "Producer"))
208 demux_info_add(demux
, "encoder", param
);
209 priv
->producer
= strdup(param
);
213 token
= strtok(NULL
, (char *)&("\x0d\x0a"));
224 static int vivo_check_file(demuxer_t
* demuxer
){
228 unsigned char buf
[2048+256];
230 int orig_pos
= stream_tell(demuxer
->stream
);
232 mp_msg(MSGT_DEMUX
,MSGL_V
,"Checking for VIVO\n");
234 c
=stream_read_char(demuxer
->stream
);
235 if(c
==-256) return 0;
237 while((c
=stream_read_char(demuxer
->stream
))>=0x80){
239 if(len
>1024) return 0;
242 mp_msg(MSGT_DEMUX
,MSGL_V
,"header block 1 size: %d\n",len
);
243 //stream_skip(demuxer->stream,len);
245 priv
=malloc(sizeof(vivo_priv_t
));
246 memset(priv
,0,sizeof(vivo_priv_t
));
250 vivo_parse_text_header(demuxer
, len
);
251 if (priv
->supported
== 0)
254 /* this is enought for check (for now) */
255 stream_read(demuxer
->stream
,buf
,len
);
257 // printf("VIVO header: '%s'\n",buf);
261 while(i
<len
&& buf
[i
]==0x0D && buf
[i
+1]==0x0A) i
+=2; // skip empty lines
262 if(strncmp(buf
+i
,"Version:Vivo/",13)) return 0; // bad version/type!
266 c
=stream_read_char(demuxer
->stream
);
269 while((c
=stream_read_char(demuxer
->stream
))>=0x80){
271 if(len
+len2
>2048) return 0;
274 mp_msg(MSGT_DEMUX
,MSGL_V
,"header block 2 size: %d\n",len2
);
275 stream_skip(demuxer
->stream
,len2
);
276 // stream_read(demuxer->stream,buf+len,len2);
279 // c=stream_read_char(demuxer->stream);
280 // printf("first packet: %02X\n",c);
282 stream_seek(demuxer
->stream
, orig_pos
);
284 return DEMUXER_TYPE_VIVO
;
287 static int audio_pos
=0;
288 static int audio_rate
=0;
291 // 0 = EOF or no stream found
292 // 1 = successfully read a packet
293 static int demux_vivo_fill_buffer(demuxer_t
*demux
, demux_stream_t
*dsds
){
294 demux_stream_t
*ds
=NULL
;
299 demux
->filepos
=stream_tell(demux
->stream
);
301 c
=stream_read_char(demux
->stream
);
302 if (c
== -256) /* EOF */
304 // printf("c=%x,%02X\n",c,c&0xf0);
307 /* ok, this works, but pts calculating from header is required! */
308 #warning "Calculate PTS from picture header!"
310 c
= stream_read_char(demux
->stream
);
311 printf("packet 0x82(pos=%u) chunk=%x\n",
312 (int)stream_tell(demux
->stream
), c
);
315 case 0x00: // header - skip it!
317 len
=stream_read_char(demux
->stream
);
318 if(len
>=0x80) len
=0x80*(len
-0x80)+stream_read_char(demux
->stream
);
319 printf("vivo extra header: %d bytes\n",len
);
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
);
331 case 0x10: // video packet
333 len
= stream_read_char(demux
->stream
);
338 case 0x20: // video packet
339 len
=stream_read_char(demux
->stream
);
342 case 0x30: // audio packet
344 len
= stream_read_char(demux
->stream
);
350 case 0x40: // audio packet
352 len
= stream_read_char(demux
->stream
);
359 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"VIVO - unknown ID found: %02X at pos %lu contact author!\n",
360 c
, stream_tell(demux
->stream
));
364 // printf("chunk=%x, len=%d\n", c, len);
366 if(!ds
|| ds
->id
<-1){
367 if(len
) stream_skip(demux
->stream
,len
);
374 if(ds
->asf_seq
!=seq
){
375 // closed segment, finalize packet:
376 ds_add_packet(ds
,ds
->asf_packet
);
378 // printf("packet!\n");
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
);
388 if((c
&0xF0)==0x20) --ds
->asf_seq
; // hack!
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
);
397 dp
->pts
=audio_rate
?((float)audio_pos
/(float)audio_rate
):0;
398 // dp->flags=keyframe;
399 // if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur);
400 dp
->pos
=demux
->filepos
;
409 static const short h263_format
[8][2] = {
416 { 320, 240 } // ??????? or 240x180 (found in vivo2) ?
419 static unsigned char* buffer
;
422 static unsigned char buf
=0;
423 static int format
, width
, height
;
425 static unsigned int x_get_bits(int n
){
430 buf
=buffer
[bufptr
++];
433 //x=(x<<1)|(buf&1);buf>>=1;
434 x
=(x
<<1)|(buf
>>7);buf
<<=1;
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)
445 /* most is hardcoded. should extend to handle all h263 streams */
446 static int h263_decode_picture_header(unsigned char *b_ptr
)
450 // for(i=0;i<16;i++) printf(" %02X",b_ptr[i]); printf("\n");
456 if (get_bits(&s
->gb
, 22) != 0x20){
457 printf("bad picture header\n");
460 skip_bits(&s
->gb
, 8); /* picture timestamp */
462 if (get_bits1(&s
->gb
) != 1){
463 printf("bad marker\n");
464 return -1; /* marker */
466 if (get_bits1(&s
->gb
) != 0){
467 printf("bad h263 id\n");
468 return -1; /* h263 id */
470 skip_bits1(&s
->gb
); /* split screen off */
471 skip_bits1(&s
->gb
); /* camera off */
472 skip_bits1(&s
->gb
); /* freeze picture release off */
474 format
= get_bits(&s
->gb
, 3);
477 printf("h263_plus = 0 format = %d\n",format
);
479 width
= h263_format
[format
][0];
480 height
= h263_format
[format
][1];
481 printf("%d x %d\n",width
,height
);
482 // if (!width) return -1;
484 printf("pict_type=%d\n",get_bits1(&s
->gb
));
485 printf("unrestricted_mv=%d\n",get_bits1(&s
->gb
));
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
));
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 */
498 printf("qscale=%d\n",get_bits(&s
->gb
, 5));
499 skip_bits1(&s
->gb
); /* Continuous Presence Multipoint mode: off */
501 printf("h263_plus = 1\n");
503 if (get_bits(&s
->gb
, 3) != 1){
504 printf("H.263v2 A error\n");
507 if (get_bits(&s
->gb
, 3) != 6){ /* custom source format */
508 printf("custom source format\n");
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)
517 skip_bits(&s
->gb
, 7);
518 skip_bits(&s
->gb
, 4); /* aspect ratio */
519 width
= (get_bits(&s
->gb
, 9) + 1) * 4;
521 height
= get_bits(&s
->gb
, 9) * 4;
522 printf("%d x %d\n",width
,height
);
525 printf("qscale=%d\n",get_bits(&s
->gb
, 5));
529 while (get_bits1(&s
->gb
) != 0) {
530 skip_bits(&s
->gb
, 8);
534 // s->height = height;
540 static demuxer_t
* demux_open_vivo(demuxer_t
* demuxer
){
541 vivo_priv_t
* priv
=demuxer
->priv
;
543 if(!ds_fill_buffer(demuxer
->video
)){
544 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"VIVO: " MSGTR_MissingVideoStreamBug
);
550 h263_decode_picture_header(demuxer
->video
->buffer
);
552 if (vivo_param_version
!= -1)
553 priv
->version
= '0' + vivo_param_version
;
555 { sh_video_t
* sh
=new_sh_video(demuxer
,0);
557 /* viv1, viv2 (for better codecs.conf) */
558 sh
->format
= mmioFOURCC('v', 'i', 'v', priv
->version
);
566 sh
->frametime
=1.0f
/sh
->fps
;
568 /* XXX: FIXME: can't scale image. */
569 /* hotfix to disable: */
570 priv
->disp_width
= priv
->width
;
571 priv
->disp_height
= priv
->height
;
573 if (vivo_param_width
!= -1)
574 priv
->disp_width
= priv
->width
= vivo_param_width
;
576 if (vivo_param_height
!= -1)
577 priv
->disp_height
= priv
->height
= vivo_param_height
;
579 if (vivo_param_vformat
!= -1)
581 priv
->disp_width
= priv
->width
= h263_format
[vivo_param_vformat
][0];
582 priv
->disp_height
= priv
->height
= h263_format
[vivo_param_vformat
][1];
585 if (priv
->disp_width
)
586 sh
->disp_w
= priv
->disp_width
;
589 if (priv
->disp_height
)
590 sh
->disp_h
= priv
->disp_height
;
594 // emulate BITMAPINFOHEADER:
595 sh
->bih
=malloc(sizeof(BITMAPINFOHEADER
));
596 memset(sh
->bih
,0,sizeof(BITMAPINFOHEADER
));
599 sh
->bih
->biWidth
= priv
->width
;
601 sh
->bih
->biWidth
= width
;
603 sh
->bih
->biHeight
= priv
->height
;
605 sh
->bih
->biHeight
= height
;
607 sh
->bih
->biBitCount
=24;
608 sh
->bih
->biCompression
=sh
->format
;
609 sh
->bih
->biSizeImage
=sh
->bih
->biWidth
*sh
->bih
->biHeight
*3;
611 /* insert as stream */
612 demuxer
->video
->sh
=sh
;
613 sh
->ds
=demuxer
->video
;
614 demuxer
->video
->id
=0;
616 /* disable seeking */
617 demuxer
->seekable
= 0;
619 printf("VIVO Video stream %d size: display: %dx%d, codec: %ux%u\n",
620 demuxer
->video
->id
, sh
->disp_w
, sh
->disp_h
, sh
->bih
->biWidth
,
625 if (demuxer
->audio
->id
>= -1){
626 if(!ds_fill_buffer(demuxer
->audio
)){
627 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"VIVO: " MSGTR_MissingAudioStream
);
629 { sh_audio_t
* sh
=new_sh_audio(demuxer
,1);
631 /* Select audio codec */
632 if (priv
->audio_codec
== 0)
634 if (priv
->version
== '2')
635 priv
->audio_codec
= VIVO_AUDIO_SIREN
;
637 priv
->audio_codec
= VIVO_AUDIO_G723
;
639 if (vivo_param_acodec
!= NULL
)
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
;
647 if (priv
->audio_codec
== VIVO_AUDIO_G723
)
649 else if (priv
->audio_codec
== VIVO_AUDIO_SIREN
)
653 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "VIVO: Not support audio codec (%d)\n",
659 // Emulate WAVEFORMATEX struct:
660 sh
->wf
=malloc(sizeof(WAVEFORMATEX
));
661 memset(sh
->wf
,0,sizeof(WAVEFORMATEX
));
662 sh
->wf
->wFormatTag
=sh
->format
;
663 sh
->wf
->nChannels
=1; /* 1 channels for both Siren and G.723 */
665 /* Set bits per sample */
666 if (priv
->audio_codec
== VIVO_AUDIO_SIREN
)
667 sh
->wf
->wBitsPerSample
= 16;
669 if (priv
->audio_codec
== VIVO_AUDIO_G723
)
670 sh
->wf
->wBitsPerSample
= 8;
672 /* Set sampling rate */
673 if (priv
->audio_samplerate
) /* got from header */
674 sh
->wf
->nSamplesPerSec
= priv
->audio_samplerate
;
677 if (priv
->audio_codec
== VIVO_AUDIO_SIREN
)
678 sh
->wf
->nSamplesPerSec
= 16000;
679 if (priv
->audio_codec
== VIVO_AUDIO_G723
)
680 sh
->wf
->nSamplesPerSec
= 8000;
682 if (vivo_param_samplerate
!= -1)
683 sh
->wf
->nSamplesPerSec
= vivo_param_samplerate
;
685 /* Set audio bitrate */
686 if (priv
->audio_bitrate
) /* got from header */
687 sh
->wf
->nAvgBytesPerSec
= priv
->audio_bitrate
;
690 if (priv
->audio_codec
== VIVO_AUDIO_SIREN
)
691 sh
->wf
->nAvgBytesPerSec
= 2000;
692 if (priv
->audio_codec
== VIVO_AUDIO_G723
)
693 sh
->wf
->nAvgBytesPerSec
= 800;
695 if (vivo_param_abitrate
!= -1)
696 sh
->wf
->nAvgBytesPerSec
= vivo_param_abitrate
;
697 audio_rate
=sh
->wf
->nAvgBytesPerSec
;
699 if (!priv
->audio_bytesperblock
)
701 if (priv
->audio_codec
== VIVO_AUDIO_SIREN
)
702 sh
->wf
->nBlockAlign
= 40;
703 if (priv
->audio_codec
== VIVO_AUDIO_G723
)
704 sh
->wf
->nBlockAlign
= 24;
707 sh
->wf
->nBlockAlign
= priv
->audio_bytesperblock
;
708 if (vivo_param_bytesperblock
!= -1)
709 sh
->wf
->nBlockAlign
= vivo_param_bytesperblock
;
712 /* insert as stream */
713 demuxer
->audio
->sh
=sh
;
714 sh
->ds
=demuxer
->audio
;
715 demuxer
->audio
->id
=1;
723 static void demux_close_vivo(demuxer_t
*demuxer
)
725 vivo_priv_t
* priv
=demuxer
->priv
;
733 free(priv
->copyright
);
735 free(priv
->producer
);
742 demuxer_desc_t demuxer_desc_vivo
= {
746 "A'rpi, Alex Beregszasi",
749 0, // unsafe autodetect
751 demux_vivo_fill_buffer
,