LCOV - code coverage report
Current view: top level - libavformat - vivo.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 12 172 7.0 %
Date: 2017-12-14 08:27:08 Functions: 1 4 25.0 %

          Line data    Source code
       1             : /*
       2             :  * Vivo stream demuxer
       3             :  * Copyright (c) 2009 Daniel Verkamp <daniel at drv.nu>
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * @brief Vivo stream demuxer
      25             :  * @author Daniel Verkamp <daniel at drv.nu>
      26             :  * @sa http://wiki.multimedia.cx/index.php?title=Vivo
      27             :  */
      28             : 
      29             : #include "libavutil/parseutils.h"
      30             : #include "avformat.h"
      31             : #include "internal.h"
      32             : 
      33             : typedef struct VivoContext {
      34             :     int version;
      35             : 
      36             :     int type;
      37             :     int sequence;
      38             :     int length;
      39             : 
      40             :     uint8_t  text[1024 + 1];
      41             : } VivoContext;
      42             : 
      43        6130 : static int vivo_probe(AVProbeData *p)
      44             : {
      45        6130 :     const unsigned char *buf = p->buf;
      46        6130 :     unsigned c, length = 0;
      47             : 
      48             :     // stream must start with packet of type 0 and sequence number 0
      49        6130 :     if (*buf++ != 0)
      50        4954 :         return 0;
      51             : 
      52             :     // read at most 2 bytes of coded length
      53        1176 :     c = *buf++;
      54        1176 :     length = c & 0x7F;
      55        1176 :     if (c & 0x80) {
      56           7 :         c = *buf++;
      57           7 :         length = (length << 7) | (c & 0x7F);
      58             :     }
      59        1176 :     if (c & 0x80 || length > 1024 || length < 21)
      60        1176 :         return 0;
      61             : 
      62           0 :     if (memcmp(buf, "\r\nVersion:Vivo/", 15))
      63           0 :         return 0;
      64           0 :     buf += 15;
      65             : 
      66           0 :     if (*buf < '0' || *buf > '2')
      67           0 :         return 0;
      68             : 
      69           0 :     return AVPROBE_SCORE_MAX;
      70             : }
      71             : 
      72           0 : static int vivo_get_packet_header(AVFormatContext *s)
      73             : {
      74           0 :     VivoContext *vivo = s->priv_data;
      75           0 :     AVIOContext *pb = s->pb;
      76           0 :     unsigned c, get_length = 0;
      77             : 
      78           0 :     if (avio_feof(pb))
      79           0 :         return AVERROR_EOF;
      80             : 
      81           0 :     c = avio_r8(pb);
      82           0 :     if (c == 0x82) {
      83           0 :         get_length = 1;
      84           0 :         c = avio_r8(pb);
      85             :     }
      86             : 
      87           0 :     vivo->type     = c >> 4;
      88           0 :     vivo->sequence = c & 0xF;
      89             : 
      90           0 :     switch (vivo->type) {
      91           0 :     case 0:   get_length =   1; break;
      92           0 :     case 1: vivo->length = 128; break;
      93           0 :     case 2:   get_length =   1; break;
      94           0 :     case 3: vivo->length =  40; break;
      95           0 :     case 4: vivo->length =  24; break;
      96           0 :     default:
      97           0 :         av_log(s, AV_LOG_ERROR, "unknown packet type %d\n", vivo->type);
      98           0 :         return AVERROR_INVALIDDATA;
      99             :     }
     100             : 
     101           0 :     if (get_length) {
     102           0 :         c = avio_r8(pb);
     103           0 :         vivo->length = c & 0x7F;
     104           0 :         if (c & 0x80) {
     105           0 :             c = avio_r8(pb);
     106           0 :             vivo->length = (vivo->length << 7) | (c & 0x7F);
     107             : 
     108           0 :             if (c & 0x80) {
     109           0 :                 av_log(s, AV_LOG_ERROR, "coded length is more than two bytes\n");
     110           0 :                 return AVERROR_INVALIDDATA;
     111             :             }
     112             :         }
     113             :     }
     114             : 
     115           0 :     return 0;
     116             : }
     117             : 
     118           0 : static int vivo_read_header(AVFormatContext *s)
     119             : {
     120           0 :     VivoContext *vivo = s->priv_data;
     121           0 :     AVRational fps = { 1, 25};
     122             :     AVStream *ast, *vst;
     123             :     unsigned char *line, *line_end, *key, *value;
     124             :     long value_int;
     125             :     int ret, value_used;
     126           0 :     int64_t duration = 0;
     127             :     char *end_value;
     128             : 
     129           0 :     vst = avformat_new_stream(s, NULL);
     130           0 :     ast = avformat_new_stream(s, NULL);
     131           0 :     if (!ast || !vst)
     132           0 :         return AVERROR(ENOMEM);
     133             : 
     134           0 :     ast->codecpar->sample_rate = 8000;
     135             : 
     136             :     while (1) {
     137           0 :         if ((ret = vivo_get_packet_header(s)) < 0)
     138           0 :             return ret;
     139             : 
     140             :         // done reading all text header packets?
     141           0 :         if (vivo->sequence || vivo->type)
     142             :             break;
     143             : 
     144           0 :         if (vivo->length <= 1024) {
     145           0 :             avio_read(s->pb, vivo->text, vivo->length);
     146           0 :             vivo->text[vivo->length] = 0;
     147             :         } else {
     148           0 :             av_log(s, AV_LOG_WARNING, "too big header, skipping\n");
     149           0 :             avio_skip(s->pb, vivo->length);
     150           0 :             continue;
     151             :         }
     152             : 
     153           0 :         line = vivo->text;
     154           0 :         while (*line) {
     155           0 :             line_end = strstr(line, "\r\n");
     156           0 :             if (!line_end)
     157           0 :                 break;
     158             : 
     159           0 :             *line_end = 0;
     160           0 :             key = line;
     161           0 :             line = line_end + 2; // skip \r\n
     162             : 
     163           0 :             if (line_end == key) // skip blank lines
     164           0 :                 continue;
     165             : 
     166           0 :             value = strchr(key, ':');
     167           0 :             if (!value) {
     168           0 :                 av_log(s, AV_LOG_WARNING, "missing colon in key:value pair '%s'\n",
     169             :                        value);
     170           0 :                 continue;
     171             :             }
     172             : 
     173           0 :             *value++ = 0;
     174             : 
     175           0 :             av_log(s, AV_LOG_DEBUG, "header: '%s' = '%s'\n", key, value);
     176             : 
     177           0 :             value_int = strtol(value, &end_value, 10);
     178           0 :             value_used = 0;
     179           0 :             if (*end_value == 0) { // valid integer
     180           0 :                 av_log(s, AV_LOG_DEBUG, "got a valid integer (%ld)\n", value_int);
     181           0 :                 value_used = 1;
     182           0 :                 if (!strcmp(key, "Duration")) {
     183           0 :                     duration = value_int;
     184           0 :                 } else if (!strcmp(key, "Width")) {
     185           0 :                     vst->codecpar->width = value_int;
     186           0 :                 } else if (!strcmp(key, "Height")) {
     187           0 :                     vst->codecpar->height = value_int;
     188           0 :                 } else if (!strcmp(key, "TimeUnitNumerator")) {
     189           0 :                     fps.num = value_int / 1000;
     190           0 :                 } else if (!strcmp(key, "TimeUnitDenominator")) {
     191           0 :                     fps.den = value_int;
     192           0 :                 } else if (!strcmp(key, "SamplingFrequency")) {
     193           0 :                     ast->codecpar->sample_rate = value_int;
     194           0 :                 } else if (!strcmp(key, "NominalBitrate")) {
     195           0 :                 } else if (!strcmp(key, "Length")) {
     196             :                     // size of file
     197             :                 } else {
     198           0 :                     value_used = 0;
     199             :                 }
     200             :             }
     201             : 
     202           0 :             if (!strcmp(key, "Version")) {
     203           0 :                 if (sscanf(value, "Vivo/%d.", &vivo->version) != 1)
     204           0 :                     return AVERROR_INVALIDDATA;
     205           0 :                 value_used = 1;
     206           0 :             } else if (!strcmp(key, "FPS")) {
     207             :                 AVRational tmp;
     208             : 
     209           0 :                 value_used = 1;
     210           0 :                 if (!av_parse_ratio(&tmp, value, 10000, AV_LOG_WARNING, s))
     211           0 :                     fps = av_inv_q(tmp);
     212             :             }
     213             : 
     214           0 :             if (!value_used)
     215           0 :                 av_dict_set(&s->metadata, key, value, 0);
     216             :         }
     217             :     }
     218             : 
     219           0 :     avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
     220           0 :     avpriv_set_pts_info(vst, 64, fps.num, fps.den);
     221           0 :     if (duration)
     222           0 :         s->duration = av_rescale(duration, 1000, 1);
     223             : 
     224           0 :     vst->start_time        = 0;
     225           0 :     vst->codecpar->codec_tag  = 0;
     226           0 :     vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     227             : 
     228           0 :     if (vivo->version == 1) {
     229           0 :         vst->codecpar->codec_id = AV_CODEC_ID_H263;
     230           0 :         ast->codecpar->codec_id = AV_CODEC_ID_G723_1;
     231           0 :         ast->codecpar->bits_per_coded_sample = 8;
     232           0 :         ast->codecpar->block_align = 24;
     233           0 :         ast->codecpar->bit_rate = 6400;
     234             :     }
     235             : 
     236           0 :     ast->start_time        = 0;
     237           0 :     ast->codecpar->codec_tag  = 0;
     238           0 :     ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     239           0 :     ast->codecpar->channels = 1;
     240             : 
     241           0 :     return 0;
     242             : }
     243             : 
     244           0 : static int vivo_read_packet(AVFormatContext *s, AVPacket *pkt)
     245             : {
     246           0 :     VivoContext *vivo = s->priv_data;
     247           0 :     AVIOContext *pb = s->pb;
     248           0 :     unsigned old_sequence = vivo->sequence, old_type = vivo->type;
     249           0 :     int stream_index, ret = 0;
     250             : 
     251           0 : restart:
     252             : 
     253           0 :     if (avio_feof(pb))
     254           0 :         return AVERROR_EOF;
     255             : 
     256           0 :     switch (vivo->type) {
     257           0 :     case 0:
     258           0 :         avio_skip(pb, vivo->length);
     259           0 :         if ((ret = vivo_get_packet_header(s)) < 0)
     260           0 :             return ret;
     261           0 :         goto restart;
     262           0 :     case 1:
     263             :     case 2: // video
     264           0 :         stream_index = 0;
     265           0 :         break;
     266           0 :     case 3:
     267             :     case 4: // audio
     268           0 :         stream_index = 1;
     269           0 :         break;
     270           0 :     default:
     271           0 :         av_log(s, AV_LOG_ERROR, "unknown packet type %d\n", vivo->type);
     272           0 :         return AVERROR_INVALIDDATA;
     273             :     }
     274             : 
     275           0 :     if ((ret = av_get_packet(pb, pkt, vivo->length)) < 0)
     276           0 :         goto fail;
     277             : 
     278             :     // get next packet header
     279           0 :     if ((ret = vivo_get_packet_header(s)) < 0)
     280           0 :         goto fail;
     281             : 
     282           0 :     while (vivo->sequence == old_sequence &&
     283           0 :            (((vivo->type - 1) >> 1) == ((old_type - 1) >> 1))) {
     284           0 :         if (avio_feof(pb)) {
     285           0 :             ret = AVERROR_EOF;
     286           0 :             break;
     287             :         }
     288             : 
     289           0 :         if ((ret = av_append_packet(pb, pkt, vivo->length)) < 0)
     290           0 :             break;
     291             : 
     292             :         // get next packet header
     293           0 :         if ((ret = vivo_get_packet_header(s)) < 0)
     294           0 :             break;
     295             :     }
     296             : 
     297           0 :     pkt->stream_index = stream_index;
     298             : 
     299           0 : fail:
     300           0 :     if (ret < 0)
     301           0 :         av_packet_unref(pkt);
     302           0 :     return ret;
     303             : }
     304             : 
     305             : AVInputFormat ff_vivo_demuxer = {
     306             :     .name           = "vivo",
     307             :     .long_name      = NULL_IF_CONFIG_SMALL("Vivo"),
     308             :     .priv_data_size = sizeof(VivoContext),
     309             :     .read_probe     = vivo_probe,
     310             :     .read_header    = vivo_read_header,
     311             :     .read_packet    = vivo_read_packet,
     312             :     .extensions     = "viv",
     313             : };

Generated by: LCOV version 1.13