LCOV - code coverage report
Current view: top level - libavformat - gdv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 83 3.6 %
Date: 2017-12-16 01:21:47 Functions: 1 3 33.3 %

          Line data    Source code
       1             : /*
       2             :  * Gremlin Digital Video demuxer
       3             :  * Copyright (c) 2017 Paul B Mahol
       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             : #include "libavutil/intreadwrite.h"
      23             : 
      24             : #include "avformat.h"
      25             : #include "avio.h"
      26             : #include "internal.h"
      27             : 
      28             : typedef struct GDVContext {
      29             :     int is_first_video;
      30             :     int is_audio;
      31             :     int audio_size;
      32             :     int audio_stream_index;
      33             :     int video_stream_index;
      34             :     unsigned pal[256];
      35             : } GDVContext;
      36             : 
      37        6130 : static int gdv_read_probe(AVProbeData *p)
      38             : {
      39        6130 :     if (AV_RL32(p->buf) == 0x29111994)
      40           0 :         return AVPROBE_SCORE_MAX;
      41             : 
      42        6130 :     return 0;
      43             : }
      44             : 
      45             : static struct {
      46             :     uint16_t id;
      47             :     uint16_t width;
      48             :     uint16_t height;
      49             : } FixedSize[] = {
      50             :     { 0, 320, 200},
      51             :     { 1, 640, 200},
      52             :     { 2, 320, 167},
      53             :     { 3, 320, 180},
      54             :     { 4, 320, 400},
      55             :     { 5, 320, 170},
      56             :     { 6, 160,  85},
      57             :     { 7, 160,  83},
      58             :     { 8, 160,  90},
      59             :     { 9, 280, 128},
      60             :     {10, 320, 240},
      61             :     {11, 320, 201},
      62             :     {16, 640, 400},
      63             :     {17, 640, 200},
      64             :     {18, 640, 180},
      65             :     {19, 640, 167},
      66             :     {20, 640, 170},
      67             :     {21, 320, 240}
      68             : };
      69             : 
      70           0 : static int gdv_read_header(AVFormatContext *ctx)
      71             : {
      72           0 :     GDVContext *gdv = ctx->priv_data;
      73           0 :     AVIOContext *pb = ctx->pb;
      74             :     AVStream *vst, *ast;
      75             :     unsigned fps, snd_flags, vid_depth, size_id;
      76             : 
      77           0 :     avio_skip(pb, 4);
      78           0 :     size_id = avio_rl16(pb);
      79             : 
      80           0 :     vst = avformat_new_stream(ctx, 0);
      81           0 :     if (!vst)
      82           0 :         return AVERROR(ENOMEM);
      83             : 
      84           0 :     vst->start_time        = 0;
      85           0 :     vst->duration          =
      86           0 :     vst->nb_frames         = avio_rl16(pb);
      87             : 
      88           0 :     fps = avio_rl16(pb);
      89           0 :     snd_flags = avio_rl16(pb);
      90           0 :     if (snd_flags & 1) {
      91           0 :         ast = avformat_new_stream(ctx, 0);
      92           0 :         if (!ast)
      93           0 :             return AVERROR(ENOMEM);
      94             : 
      95           0 :         ast->start_time = 0;
      96           0 :         ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
      97           0 :         ast->codecpar->codec_tag   = 0;
      98           0 :         ast->codecpar->sample_rate = avio_rl16(pb);
      99           0 :         ast->codecpar->channels    = 1 + !!(snd_flags & 2);
     100           0 :         if (snd_flags & 8) {
     101           0 :             ast->codecpar->codec_id = AV_CODEC_ID_GREMLIN_DPCM;
     102             :         } else {
     103           0 :             ast->codecpar->codec_id = (snd_flags & 4) ? AV_CODEC_ID_PCM_S16LE : AV_CODEC_ID_PCM_U8;
     104             :         }
     105             : 
     106           0 :         avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
     107           0 :         gdv->audio_size = (ast->codecpar->sample_rate / fps) *
     108           0 :                            ast->codecpar->channels * (1 + !!(snd_flags & 4)) / (1 + !!(snd_flags & 8));
     109           0 :         gdv->is_audio = 1;
     110             :     } else {
     111           0 :         avio_skip(pb, 2);
     112             :     }
     113           0 :     vid_depth = avio_rl16(pb);
     114           0 :     avio_skip(pb, 4);
     115             : 
     116           0 :     vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     117           0 :     vst->codecpar->codec_id   = AV_CODEC_ID_GDV;
     118           0 :     vst->codecpar->codec_tag  = 0;
     119           0 :     vst->codecpar->width      = avio_rl16(pb);
     120           0 :     vst->codecpar->height     = avio_rl16(pb);
     121             : 
     122           0 :     if (vst->codecpar->width == 0 || vst->codecpar->height == 0) {
     123             :         int i;
     124             : 
     125           0 :         for (i = 0; i < FF_ARRAY_ELEMS(FixedSize) - 1; i++) {
     126           0 :             if (FixedSize[i].id == size_id)
     127           0 :                 break;
     128             :         }
     129             : 
     130           0 :         vst->codecpar->width  = FixedSize[i].width;
     131           0 :         vst->codecpar->height = FixedSize[i].height;
     132             :     }
     133             : 
     134           0 :     avpriv_set_pts_info(vst, 64, 1, fps);
     135             : 
     136           0 :     if (vid_depth & 1) {
     137             :         int i;
     138             : 
     139           0 :         for (i = 0; i < 256; i++) {
     140           0 :             unsigned r = avio_r8(pb);
     141           0 :             unsigned g = avio_r8(pb);
     142           0 :             unsigned b = avio_r8(pb);
     143           0 :             gdv->pal[i] = 0xFFU << 24 | r << 18 | g << 10 | b << 2;
     144             :         }
     145             :     }
     146             : 
     147           0 :     gdv->is_first_video = 1;
     148             : 
     149           0 :     return 0;
     150             : }
     151             : 
     152           0 : static int gdv_read_packet(AVFormatContext *ctx, AVPacket *pkt)
     153             : {
     154           0 :     GDVContext *gdv = ctx->priv_data;
     155           0 :     AVIOContext *pb = ctx->pb;
     156             :     int ret;
     157             : 
     158           0 :     if (avio_feof(pb))
     159           0 :         return pb->error ? pb->error : AVERROR_EOF;
     160             : 
     161           0 :     if (gdv->audio_size && gdv->is_audio) {
     162           0 :         ret = av_get_packet(pb, pkt, gdv->audio_size);
     163           0 :         if (ret < 0)
     164           0 :             return ret;
     165           0 :         pkt->stream_index = 1;
     166           0 :         gdv->is_audio = 0;
     167             :     } else {
     168             :         uint8_t *pal;
     169             : 
     170           0 :         if (avio_rl16(pb) != 0x1305)
     171           0 :             return AVERROR_INVALIDDATA;
     172           0 :         ret = av_get_packet(pb, pkt, 4 + avio_rl16(pb));
     173           0 :         if (ret < 0)
     174           0 :             return ret;
     175           0 :         pkt->stream_index = 0;
     176           0 :         gdv->is_audio = 1;
     177             : 
     178           0 :         if (gdv->is_first_video) {
     179           0 :             pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
     180             :                                           AVPALETTE_SIZE);
     181           0 :             if (!pal) {
     182           0 :                 av_packet_unref(pkt);
     183           0 :                 return AVERROR(ENOMEM);
     184             :             }
     185           0 :             memcpy(pal, gdv->pal, AVPALETTE_SIZE);
     186           0 :             pkt->flags |= AV_PKT_FLAG_KEY;
     187           0 :             gdv->is_first_video = 0;
     188             :         }
     189             :     }
     190             : 
     191           0 :     return 0;
     192             : }
     193             : 
     194             : AVInputFormat ff_gdv_demuxer = {
     195             :     .name           = "gdv",
     196             :     .long_name      = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"),
     197             :     .priv_data_size = sizeof(GDVContext),
     198             :     .read_probe     = gdv_read_probe,
     199             :     .read_header    = gdv_read_header,
     200             :     .read_packet    = gdv_read_packet,
     201             : };

Generated by: LCOV version 1.13