📄 demux_viv.c
字号:
// VIVO file parser by A'rpi// VIVO text header parser and audio support by alex#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h> /* strtok */#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream.h"#include "demuxer.h"#include "stheader.h"#include "bswap.h"/* parameters ! */int vivo_param_version = -1;char *vivo_param_acodec = NULL;int vivo_param_abitrate = -1;int vivo_param_samplerate = -1;int vivo_param_bytesperblock = -1;int vivo_param_width = -1;int vivo_param_height = -1;int vivo_param_vformat = -1;/* VIVO audio standards from vivog723.acm: G.723: FormatTag = 0x111 Channels = 1 - mono SamplesPerSec = 8000 - 8khz AvgBytesPerSec = 800 BlockAlign (bytes per block) = 24 BitsPerSample = 8 Siren: FormatTag = 0x112 Channels = 1 - mono SamplesPerSec = 16000 - 16khz AvgBytesPerSec = 2000 BlockAlign (bytes per block) = 40 BitsPerSample = 8*///enum { VIVO_AUDIO_G723, VIVO_AUDIO_SIREN };#define VIVO_AUDIO_G723 1#define VIVO_AUDIO_SIREN 2typedef struct { /* generic */ char version; int supported; /* info */ char *title; char *author; char *copyright; char *producer; /* video */ float fps; int width; int height; int disp_width; int disp_height; /* audio */ int audio_codec; int audio_bitrate; int audio_samplerate; int audio_bytesperblock;} vivo_priv_t;/* parse all possible extra headers *//* (audio headers are seperate - mostly with recordtype=3 or 4) */#define TEXTPARSE_ALL 1static void vivo_parse_text_header(demuxer_t *demux, int header_len){ vivo_priv_t* priv = demux->priv; char *buf; int i; char *token; char *opt, *param; int parser_in_audio_block = 0; if (!demux->priv) { priv = malloc(sizeof(vivo_priv_t)); memset(priv, 0, sizeof(vivo_priv_t)); demux->priv = priv; priv->supported = 0; } buf = malloc(header_len); opt = malloc(header_len); param = malloc(header_len); stream_read(demux->stream, buf, header_len); i=0; while(i<header_len && buf[i]==0x0D && buf[i+1]==0x0A) i+=2; // skip empty lines token = strtok(buf, (char *)&("\x0d\x0a")); while (token && (header_len>2)) { header_len -= strlen(token)+2; if (sscanf(token, "%[^:]:%[^\n]", opt, param) != 2) { mp_msg(MSGT_DEMUX, MSGL_V, "viv_text_header_parser: bad line: '%s' at ~%p\n", token, stream_tell(demux->stream)); break; } mp_dbg(MSGT_DEMUX, MSGL_DBG3, "token: '%s' (%d bytes/%d bytes left)\n", token, strlen(token), header_len); mp_dbg(MSGT_DEMUX, MSGL_DBG3, "token => o: '%s', p: '%s'\n", opt, param); /* checking versions: only v1 or v2 is suitable (or known?:) */ if (!strcmp(opt, "Version")) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Version: %s\n", param); if (!strncmp(param, "Vivo/1", 6) || !strncmp(param, "Vivo/2", 6)) { priv->supported = 1; /* save major version for fourcc */ priv->version = param[5]; } } /* video specific */ if (!strcmp(opt, "FPS")) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "FPS: %f\n", atof(param)); priv->fps = atof(param); } if (!strcmp(opt, "Width")) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Width: %d\n", atoi(param)); priv->width = atoi(param); } if (!strcmp(opt, "Height")) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Height: %d\n", atoi(param)); priv->height = atoi(param); } if (!strcmp(opt, "DisplayWidth")) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Display Width: %d\n", atoi(param)); priv->disp_width = atoi(param); } if (!strcmp(opt, "DisplayHeight")) { mp_msg(MSGT_DEMUX, MSGL_DBG2, "Display Height: %d\n", atoi(param)); priv->disp_height = atoi(param); } /* audio specific */ if (!strcmp(opt, "RecordType")) { /* no audio recordblock by Vivo/1.00, 3 and 4 by Vivo/2.00 */ if ((atoi(param) == 3) || (atoi(param) == 4)) parser_in_audio_block = 1; else parser_in_audio_block = 0; } if (!strcmp(opt, "NominalBitrate")) { priv->audio_bitrate = atoi(param); if (priv->audio_bitrate == 2000) priv->audio_codec = VIVO_AUDIO_SIREN; if (priv->audio_bitrate == 800) priv->audio_codec = VIVO_AUDIO_G723; } if (!strcmp(opt, "SamplingFrequency")) { priv->audio_samplerate = atoi(param); if (priv->audio_samplerate == 16000) priv->audio_codec = VIVO_AUDIO_SIREN; if (priv->audio_samplerate == 8000) priv->audio_codec = VIVO_AUDIO_G723; } if (!strcmp(opt, "Length") && (parser_in_audio_block == 1)) { priv->audio_bytesperblock = atoi(param); /* 24 or 40 kbps */ if (priv->audio_bytesperblock == 40) priv->audio_codec = VIVO_AUDIO_SIREN; if (priv->audio_bytesperblock == 24) priv->audio_codec = VIVO_AUDIO_G723; } /* only for displaying some informations about movie*/ if (!strcmp(opt, "Title")) { demux_info_add(demux, "name", param); priv->title = strdup(param); } if (!strcmp(opt, "Author")) { demux_info_add(demux, "author", param); priv->author = strdup(param); } if (!strcmp(opt, "Copyright")) { demux_info_add(demux, "copyright", param); priv->copyright = strdup(param); } if (!strcmp(opt, "Producer")) { demux_info_add(demux, "encoder", param); priv->producer = strdup(param); } /* get next token */ token = strtok(NULL, (char *)&("\x0d\x0a")); } if (buf) free(buf); if (opt) free(opt); if (param) free(param);}int vivo_check_file(demuxer_t* demuxer){ int i=0; int len; int c; unsigned char buf[2048+256]; vivo_priv_t* priv; int orig_pos = stream_tell(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"Checking for VIVO\n"); c=stream_read_char(demuxer->stream); if(c==-256) return 0; len=0; while((c=stream_read_char(demuxer->stream))>=0x80){ len+=0x80*(c-0x80); if(len>1024) return 0; } len+=c; mp_msg(MSGT_DEMUX,MSGL_V,"header block 1 size: %d\n",len); //stream_skip(demuxer->stream,len); priv=malloc(sizeof(vivo_priv_t)); memset(priv,0,sizeof(vivo_priv_t)); demuxer->priv=priv;#if 0 vivo_parse_text_header(demuxer, len); if (priv->supported == 0) return 0;#else /* this is enought for check (for now) */ stream_read(demuxer->stream,buf,len); buf[len]=0;// printf("VIVO header: '%s'\n",buf); // parse header: i=0; while(i<len && buf[i]==0x0D && buf[i+1]==0x0A) i+=2; // skip empty lines if(strncmp(buf+i,"Version:Vivo/",13)) return 0; // bad version/type!#endif#if 0 c=stream_read_char(demuxer->stream); if(c) return 0; len2=0; while((c=stream_read_char(demuxer->stream))>=0x80){ len2+=0x80*(c-0x80); if(len+len2>2048) return 0; } len2+=c; mp_msg(MSGT_DEMUX,MSGL_V,"header block 2 size: %d\n",len2); stream_skip(demuxer->stream,len2);// stream_read(demuxer->stream,buf+len,len2);#endif // c=stream_read_char(demuxer->stream);// printf("first packet: %02X\n",c); stream_seek(demuxer->stream, orig_pos);return 1;}static int audio_pos=0;static int audio_rate=0;// return value:// 0 = EOF or no stream found// 1 = successfully read a packetint demux_vivo_fill_buffer(demuxer_t *demux){ demux_stream_t *ds=NULL; int c; int len=0; int seq; int prefix=0; demux->filepos=stream_tell(demux->stream); c=stream_read_char(demux->stream); if (c == -256) /* EOF */ return 0;// printf("c=%x,%02X\n",c,c&0xf0); if (c == 0x82) { /* ok, this works, but pts calculating from header is required! */#warning "Calculate PTS from picture header!" prefix = 1; c = stream_read_char(demux->stream); printf("packet 0x82(pos=%u) chunk=%x\n", (int)stream_tell(demux->stream), c); } switch(c&0xF0){ case 0x00: // header - skip it! { len=stream_read_char(demux->stream); if(len>=0x80) len=0x80*(len-0x80)+stream_read_char(demux->stream); printf("vivo extra header: %d bytes\n",len);#ifdef TEXTPARSE_ALL{ int pos; /* also try to parse all headers */ pos = stream_tell(demux->stream); vivo_parse_text_header(demux, len); stream_seek(demux->stream, pos);}#endif break; } case 0x10: // video packet if (prefix == 1) len = stream_read_char(demux->stream); else len=128; ds=demux->video; break; case 0x20: // video packet len=stream_read_char(demux->stream); ds=demux->video; break; case 0x30: // audio packet if (prefix == 1) len = stream_read_char(demux->stream); else len=40; /* 40kbps */ ds=demux->audio; audio_pos+=len; break; case 0x40: // audio packet if (prefix == 1) len = stream_read_char(demux->stream); else len=24; /* 24kbps */ ds=demux->audio; audio_pos+=len; break; default: mp_msg(MSGT_DEMUX,MSGL_WARN,"VIVO - unknown ID found: %02X at pos %lu contact author!\n", c, stream_tell(demux->stream)); return 0; }// printf("chunk=%x, len=%d\n", c, len); if(!ds || ds->id<-1){ if(len) stream_skip(demux->stream,len); return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -