00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include "libavutil/parseutils.h"
00030 #include "avformat.h"
00031 #include "internal.h"
00032
00033 typedef struct VivoContext {
00034 int version;
00035
00036 int type;
00037 int sequence;
00038 int length;
00039
00040 uint8_t text[1024 + 1];
00041 } VivoContext;
00042
00043 static int vivo_probe(AVProbeData *p)
00044 {
00045 const unsigned char *buf = p->buf;
00046 unsigned c, length = 0;
00047
00048
00049 if (*buf++ != 0)
00050 return 0;
00051
00052
00053 c = *buf++;
00054 length = c & 0x7F;
00055 if (c & 0x80) {
00056 c = *buf++;
00057 length = (length << 7) | (c & 0x7F);
00058 }
00059 if (c & 0x80 || length > 1024 || length < 21)
00060 return 0;
00061
00062 if (memcmp(buf, "\r\nVersion:Vivo/", 15))
00063 return 0;
00064 buf += 15;
00065
00066 if (*buf < '0' && *buf > '2')
00067 return 0;
00068
00069 return AVPROBE_SCORE_MAX;
00070 }
00071
00072 static int vivo_get_packet_header(AVFormatContext *s)
00073 {
00074 VivoContext *vivo = s->priv_data;
00075 AVIOContext *pb = s->pb;
00076 unsigned c, get_length = 0;
00077
00078 if (url_feof(pb))
00079 return AVERROR_EOF;
00080
00081 c = avio_r8(pb);
00082 if (c == 0x82) {
00083 get_length = 1;
00084 c = avio_r8(pb);
00085 }
00086
00087 vivo->type = c >> 4;
00088 vivo->sequence = c & 0xF;
00089
00090 switch (vivo->type) {
00091 case 0: get_length = 1; break;
00092 case 1: vivo->length = 128; break;
00093 case 2: get_length = 1; break;
00094 case 3: vivo->length = 40; break;
00095 case 4: vivo->length = 24; break;
00096 default:
00097 av_log(s, AV_LOG_ERROR, "unknown packet type %d\n", vivo->type);
00098 return AVERROR_INVALIDDATA;
00099 }
00100
00101 if (get_length) {
00102 c = avio_r8(pb);
00103 vivo->length = c & 0x7F;
00104 if (c & 0x80) {
00105 c = avio_r8(pb);
00106 vivo->length = (vivo->length << 7) | (c & 0x7F);
00107
00108 if (c & 0x80) {
00109 av_log(s, AV_LOG_ERROR, "coded length is more than two bytes\n");
00110 return AVERROR_INVALIDDATA;
00111 }
00112 }
00113 }
00114
00115 return 0;
00116 }
00117
00118 static int vivo_read_header(AVFormatContext *s)
00119 {
00120 VivoContext *vivo = s->priv_data;
00121 AVRational fps = { 1, 25};
00122 AVStream *ast, *vst;
00123 unsigned char *line, *line_end, *key, *value;
00124 long value_int;
00125 int ret, value_used;
00126 int64_t duration = 0;
00127 char *end_value;
00128
00129 vst = avformat_new_stream(s, NULL);
00130 ast = avformat_new_stream(s, NULL);
00131 if (!ast || !vst)
00132 return AVERROR(ENOMEM);
00133
00134 ast->codec->sample_rate = 8000;
00135
00136 while (1) {
00137 if ((ret = vivo_get_packet_header(s)) < 0)
00138 return ret;
00139
00140
00141 if (vivo->sequence || vivo->type)
00142 break;
00143
00144 if (vivo->length <= 1024) {
00145 avio_read(s->pb, vivo->text, vivo->length);
00146 vivo->text[vivo->length] = 0;
00147 } else {
00148 av_log(s, AV_LOG_WARNING, "too big header, skipping\n");
00149 avio_skip(s->pb, vivo->length);
00150 continue;
00151 }
00152
00153 line = vivo->text;
00154 while (*line) {
00155 line_end = strstr(line, "\r\n");
00156 if (!line_end)
00157 break;
00158
00159 *line_end = 0;
00160 key = line;
00161 line = line_end + 2;
00162
00163 if (line_end == key)
00164 continue;
00165
00166 value = strchr(key, ':');
00167 if (!value) {
00168 av_log(s, AV_LOG_WARNING, "missing colon in key:value pair '%s'\n",
00169 value);
00170 continue;
00171 }
00172
00173 *value++ = 0;
00174
00175 av_log(s, AV_LOG_DEBUG, "header: '%s' = '%s'\n", key, value);
00176
00177 value_int = strtol(value, &end_value, 10);
00178 value_used = 0;
00179 if (*end_value == 0) {
00180 av_log(s, AV_LOG_DEBUG, "got a valid integer (%ld)\n", value_int);
00181 value_used = 1;
00182 if (!strcmp(key, "Duration")) {
00183 duration = value_int;
00184 } else if (!strcmp(key, "Width")) {
00185 vst->codec->width = value_int;
00186 } else if (!strcmp(key, "Height")) {
00187 vst->codec->height = value_int;
00188 } else if (!strcmp(key, "TimeUnitNumerator")) {
00189 fps.num = value_int / 1000;
00190 } else if (!strcmp(key, "TimeUnitDenominator")) {
00191 fps.den = value_int;
00192 } else if (!strcmp(key, "SamplingFrequency")) {
00193 ast->codec->sample_rate = value_int;
00194 } else if (!strcmp(key, "NominalBitrate")) {
00195 } else if (!strcmp(key, "Length")) {
00196
00197 } else {
00198 value_used = 0;
00199 }
00200 }
00201
00202 if (!strcmp(key, "Version")) {
00203 if (sscanf(value, "Vivo/%d.", &vivo->version) != 1)
00204 return AVERROR_INVALIDDATA;
00205 value_used = 1;
00206 } else if (!strcmp(key, "FPS")) {
00207 AVRational tmp;
00208
00209 value_used = 1;
00210 if (!av_parse_ratio(&tmp, value, 10000, AV_LOG_WARNING, s))
00211 fps = av_inv_q(tmp);
00212 }
00213
00214 if (!value_used)
00215 av_dict_set(&s->metadata, key, value, 0);
00216 }
00217 }
00218
00219 avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
00220 avpriv_set_pts_info(vst, 64, fps.num, fps.den);
00221 if (duration)
00222 s->duration = av_rescale(duration, 1000, 1);
00223
00224 vst->start_time = 0;
00225 vst->codec->codec_tag = 0;
00226 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00227
00228 if (vivo->version == 1) {
00229 vst->codec->codec_id = AV_CODEC_ID_H263;
00230 ast->codec->codec_id = AV_CODEC_ID_G723_1;
00231 ast->codec->bits_per_coded_sample = 8;
00232 ast->codec->block_align = 24;
00233 ast->codec->bit_rate = 6400;
00234 }
00235
00236 ast->start_time = 0;
00237 ast->codec->codec_tag = 0;
00238 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00239 ast->codec->channels = 1;
00240
00241 return 0;
00242 }
00243
00244 static int vivo_read_packet(AVFormatContext *s, AVPacket *pkt)
00245 {
00246 VivoContext *vivo = s->priv_data;
00247 AVIOContext *pb = s->pb;
00248 unsigned old_sequence = vivo->sequence, old_type = vivo->type;
00249 int stream_index, ret = 0;
00250
00251 restart:
00252
00253 if (url_feof(pb))
00254 return AVERROR_EOF;
00255
00256 switch (vivo->type) {
00257 case 0:
00258 avio_skip(pb, vivo->length);
00259 if ((ret = vivo_get_packet_header(s)) < 0)
00260 return ret;
00261 goto restart;
00262 case 1:
00263 case 2:
00264 stream_index = 0;
00265 break;
00266 case 3:
00267 case 4:
00268 stream_index = 1;
00269 break;
00270 default:
00271 av_log(s, AV_LOG_ERROR, "unknown packet type %d\n", vivo->type);
00272 return AVERROR_INVALIDDATA;
00273 }
00274
00275 if ((ret = av_get_packet(pb, pkt, vivo->length)) < 0)
00276 goto fail;
00277
00278
00279 if ((ret = vivo_get_packet_header(s)) < 0)
00280 goto fail;
00281
00282 while (vivo->sequence == old_sequence &&
00283 (((vivo->type - 1) >> 1) == ((old_type - 1) >> 1))) {
00284 if (url_feof(pb)) {
00285 ret = AVERROR_EOF;
00286 break;
00287 }
00288
00289 if ((ret = av_append_packet(pb, pkt, vivo->length)) < 0)
00290 break;
00291
00292
00293 if ((ret = vivo_get_packet_header(s)) < 0)
00294 break;
00295 }
00296
00297 pkt->stream_index = stream_index;
00298
00299 fail:
00300 if (ret < 0)
00301 av_free_packet(pkt);
00302 return ret;
00303 }
00304
00305 AVInputFormat ff_vivo_demuxer = {
00306 .name = "vivo",
00307 .long_name = NULL_IF_CONFIG_SMALL("Vivo"),
00308 .priv_data_size = sizeof(VivoContext),
00309 .read_probe = vivo_probe,
00310 .read_header = vivo_read_header,
00311 .read_packet = vivo_read_packet,
00312 .extensions = "viv",
00313 };