LCOV - code coverage report
Current view: top level - libavformat - mtv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 69 90 76.7 %
Date: 2017-12-15 18:13:28 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * mtv demuxer
       3             :  * Copyright (c) 2006 Reynaldo H. Verdejo Pinochet
       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             :  * MTV demuxer.
      25             :  */
      26             : 
      27             : #include "libavutil/bswap.h"
      28             : #include "libavutil/intreadwrite.h"
      29             : #include "avformat.h"
      30             : #include "internal.h"
      31             : 
      32             : #define MTV_ASUBCHUNK_DATA_SIZE 500
      33             : #define MTV_HEADER_SIZE 512
      34             : #define MTV_AUDIO_PADDING_SIZE 12
      35             : #define MTV_IMAGE_DEFAULT_BPP 16
      36             : #define MTV_AUDIO_SAMPLING_RATE 44100
      37             : 
      38             : typedef struct MTVDemuxContext {
      39             : 
      40             :     unsigned int file_size;         ///< filesize, not always right
      41             :     unsigned int segments;          ///< number of 512 byte segments
      42             :     unsigned int audio_identifier;  ///< 'MP3' on all files I have seen
      43             :     unsigned int audio_br;          ///< bitrate of audio channel (mp3)
      44             :     unsigned int img_colorfmt;      ///< frame colorfmt rgb 565/555
      45             :     unsigned int img_bpp;           ///< frame bits per pixel
      46             :     unsigned int img_width;
      47             :     unsigned int img_height;
      48             :     unsigned int img_segment_size;  ///< size of image segment
      49             :     unsigned int video_fps;
      50             :     unsigned int full_segment_size;
      51             : 
      52             : } MTVDemuxContext;
      53             : 
      54        6130 : static int mtv_probe(AVProbeData *p)
      55             : {
      56             :     /* we need at least 57 bytes from the header
      57             :      * to try parsing all required fields
      58             :      */
      59        6130 :     if (p->buf_size < 57)
      60           2 :         return 0;
      61             : 
      62             :     /* Magic is 'AMV' */
      63        6128 :     if (*p->buf != 'A' || *(p->buf + 1) != 'M' || *(p->buf + 2) != 'V')
      64        6127 :         return 0;
      65             : 
      66             :     /* Audio magic is always MP3 */
      67           1 :     if (p->buf[43] != 'M' || p->buf[44] != 'P' || p->buf[45] != '3')
      68           0 :         return 0;
      69             : 
      70             :     /* Check for nonzero in bpp and (width|height) header fields */
      71           1 :     if(!(p->buf[51] && AV_RL16(&p->buf[52]) | AV_RL16(&p->buf[54])))
      72           0 :         return 0;
      73             : 
      74             :     /* If width or height are 0 then imagesize header field should not */
      75           1 :     if(!AV_RL16(&p->buf[52]) || !AV_RL16(&p->buf[54]))
      76             :     {
      77           0 :         if(!!AV_RL16(&p->buf[56]))
      78           0 :             return AVPROBE_SCORE_EXTENSION;
      79             :         else
      80           0 :             return 0;
      81             :     }
      82             : 
      83             :     /* Image bpp is not an absolutely required
      84             :      * field as we latter claim it should be 16
      85             :      * no matter what. All samples in the wild
      86             :      * are RGB565/555.
      87             :      */
      88           1 :     if(p->buf[51] != MTV_IMAGE_DEFAULT_BPP)
      89           0 :         return AVPROBE_SCORE_EXTENSION / 2;
      90             : 
      91             :     /* We had enough data to parse header values
      92             :      * but we expect to be able to get 512 bytes
      93             :      * of header to be sure.
      94             :      */
      95           1 :     if (p->buf_size < MTV_HEADER_SIZE)
      96           0 :         return AVPROBE_SCORE_EXTENSION;
      97             : 
      98           1 :     return AVPROBE_SCORE_MAX;
      99             : }
     100             : 
     101           1 : static int mtv_read_header(AVFormatContext *s)
     102             : {
     103           1 :     MTVDemuxContext *mtv = s->priv_data;
     104           1 :     AVIOContext   *pb  = s->pb;
     105             :     AVStream        *st;
     106             :     unsigned int    audio_subsegments;
     107             : 
     108           1 :     avio_skip(pb, 3);
     109           1 :     mtv->file_size         = avio_rl32(pb);
     110           1 :     mtv->segments          = avio_rl32(pb);
     111           1 :     avio_skip(pb, 32);
     112           1 :     mtv->audio_identifier  = avio_rl24(pb);
     113           1 :     mtv->audio_br          = avio_rl16(pb);
     114           1 :     mtv->img_colorfmt      = avio_rl24(pb);
     115           1 :     mtv->img_bpp           = avio_r8(pb);
     116           1 :     mtv->img_width         = avio_rl16(pb);
     117           1 :     mtv->img_height        = avio_rl16(pb);
     118           1 :     mtv->img_segment_size  = avio_rl16(pb);
     119             : 
     120             :     /* Assume 16bpp even if claimed otherwise.
     121             :      * We know its going to be RGBG565/555 anyway
     122             :      */
     123           1 :     if (mtv->img_bpp != MTV_IMAGE_DEFAULT_BPP) {
     124           0 :         av_log (s, AV_LOG_WARNING, "Header claims %dbpp (!= 16). Ignoring\n",
     125             :                 mtv->img_bpp);
     126           0 :         mtv->img_bpp = MTV_IMAGE_DEFAULT_BPP;
     127             :     }
     128             : 
     129             :     /* Calculate width and height if missing from header */
     130             : 
     131           1 :     if (!mtv->img_width && mtv->img_height > 0 && mtv->img_bpp >= 8)
     132           0 :         mtv->img_width=mtv->img_segment_size / (mtv->img_bpp>>3)
     133           0 :                         / mtv->img_height;
     134             : 
     135           1 :     if (!mtv->img_height && mtv->img_width > 0 && mtv->img_bpp >= 8)
     136           0 :         mtv->img_height=mtv->img_segment_size / (mtv->img_bpp>>3)
     137           0 :                         / mtv->img_width;
     138             : 
     139           1 :     if(!mtv->img_height || !mtv->img_width || !mtv->img_segment_size){
     140           0 :         av_log(s, AV_LOG_ERROR, "width or height or segment_size is invalid and I cannot calculate them from other information\n");
     141           0 :         return AVERROR_INVALIDDATA;
     142             :     }
     143             : 
     144           1 :     avio_skip(pb, 4);
     145           1 :     audio_subsegments = avio_rl16(pb);
     146             : 
     147           1 :     if (audio_subsegments == 0) {
     148           0 :         avpriv_request_sample(s, "MTV files without audio");
     149           0 :         return AVERROR_PATCHWELCOME;
     150             :     }
     151             : 
     152           1 :     mtv->full_segment_size =
     153           2 :         audio_subsegments * (MTV_AUDIO_PADDING_SIZE + MTV_ASUBCHUNK_DATA_SIZE) +
     154           1 :         mtv->img_segment_size;
     155           1 :     mtv->video_fps         = (mtv->audio_br / 4) / audio_subsegments;
     156             : 
     157             :     // FIXME Add sanity check here
     158             : 
     159             :     // all systems go! init decoders
     160             : 
     161             :     // video - raw rgb565
     162             : 
     163           1 :     st = avformat_new_stream(s, NULL);
     164           1 :     if(!st)
     165           0 :         return AVERROR(ENOMEM);
     166             : 
     167           1 :     avpriv_set_pts_info(st, 64, 1, mtv->video_fps);
     168           1 :     st->codecpar->codec_type      = AVMEDIA_TYPE_VIDEO;
     169           1 :     st->codecpar->codec_id        = AV_CODEC_ID_RAWVIDEO;
     170           1 :     st->codecpar->format          = AV_PIX_FMT_RGB565BE;
     171           1 :     st->codecpar->width           = mtv->img_width;
     172           1 :     st->codecpar->height          = mtv->img_height;
     173           1 :     st->codecpar->extradata       = av_strdup("BottomUp");
     174           1 :     st->codecpar->extradata_size  = 9;
     175             : 
     176             :     // audio - mp3
     177             : 
     178           1 :     st = avformat_new_stream(s, NULL);
     179           1 :     if(!st)
     180           0 :         return AVERROR(ENOMEM);
     181             : 
     182           1 :     avpriv_set_pts_info(st, 64, 1, MTV_AUDIO_SAMPLING_RATE);
     183           1 :     st->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
     184           1 :     st->codecpar->codec_id        = AV_CODEC_ID_MP3;
     185           1 :     st->codecpar->bit_rate        = mtv->audio_br;
     186           1 :     st->need_parsing              = AVSTREAM_PARSE_FULL;
     187             : 
     188             :     // Jump over header
     189             : 
     190           1 :     if(avio_seek(pb, MTV_HEADER_SIZE, SEEK_SET) != MTV_HEADER_SIZE)
     191           0 :         return AVERROR(EIO);
     192             : 
     193           1 :     return 0;
     194             : 
     195             : }
     196             : 
     197         123 : static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)
     198             : {
     199         123 :     MTVDemuxContext *mtv = s->priv_data;
     200         123 :     AVIOContext *pb = s->pb;
     201             :     int ret;
     202             : 
     203         123 :     if((avio_tell(pb) - s->internal->data_offset + mtv->img_segment_size) % mtv->full_segment_size)
     204             :     {
     205          83 :         avio_skip(pb, MTV_AUDIO_PADDING_SIZE);
     206             : 
     207          83 :         ret = av_get_packet(pb, pkt, MTV_ASUBCHUNK_DATA_SIZE);
     208          83 :         if(ret < 0)
     209           3 :             return ret;
     210             : 
     211          80 :         pkt->pos -= MTV_AUDIO_PADDING_SIZE;
     212          80 :         pkt->stream_index = 1;
     213             : 
     214             :     }else
     215             :     {
     216          40 :         ret = av_get_packet(pb, pkt, mtv->img_segment_size);
     217          40 :         if(ret < 0)
     218           0 :             return ret;
     219             : 
     220          40 :         pkt->stream_index = 0;
     221             :     }
     222             : 
     223         120 :     return ret;
     224             : }
     225             : 
     226             : AVInputFormat ff_mtv_demuxer = {
     227             :     .name           = "mtv",
     228             :     .long_name      = NULL_IF_CONFIG_SMALL("MTV"),
     229             :     .priv_data_size = sizeof(MTVDemuxContext),
     230             :     .read_probe     = mtv_probe,
     231             :     .read_header    = mtv_read_header,
     232             :     .read_packet    = mtv_read_packet,
     233             : };

Generated by: LCOV version 1.13