LCOV - code coverage report
Current view: top level - libavformat - idcin.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 120 168 71.4 %
Date: 2017-12-18 13:19:42 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*
       2             :  * id Quake II CIN File Demuxer
       3             :  * Copyright (c) 2003 The FFmpeg project
       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             :  * id Quake II CIN file demuxer by Mike Melanson (melanson@pcisys.net)
      25             :  * For more information about the id CIN format, visit:
      26             :  *   http://www.csse.monash.edu.au/~timf/
      27             :  *
      28             :  * CIN is a somewhat quirky and ill-defined format. Here are some notes
      29             :  * for anyone trying to understand the technical details of this format:
      30             :  *
      31             :  * The format has no definite file signature. This is problematic for a
      32             :  * general-purpose media player that wants to automatically detect file
      33             :  * types. However, a CIN file does start with 5 32-bit numbers that
      34             :  * specify audio and video parameters. This demuxer gets around the lack
      35             :  * of file signature by performing sanity checks on those parameters.
      36             :  * Probabilistically, this is a reasonable solution since the number of
      37             :  * valid combinations of the 5 parameters is a very small subset of the
      38             :  * total 160-bit number space.
      39             :  *
      40             :  * Refer to the function idcin_probe() for the precise A/V parameters
      41             :  * that this demuxer allows.
      42             :  *
      43             :  * Next, each audio and video frame has a duration of 1/14 sec. If the
      44             :  * audio sample rate is a multiple of the common frequency 22050 Hz it will
      45             :  * divide evenly by 14. However, if the sample rate is 11025 Hz:
      46             :  *   11025 (samples/sec) / 14 (frames/sec) = 787.5 (samples/frame)
      47             :  * The way the CIN stores audio in this case is by storing 787 sample
      48             :  * frames in the first audio frame and 788 sample frames in the second
      49             :  * audio frame. Therefore, the total number of bytes in an audio frame
      50             :  * is given as:
      51             :  *   audio frame #0: 787 * (bytes/sample) * (# channels) bytes in frame
      52             :  *   audio frame #1: 788 * (bytes/sample) * (# channels) bytes in frame
      53             :  *   audio frame #2: 787 * (bytes/sample) * (# channels) bytes in frame
      54             :  *   audio frame #3: 788 * (bytes/sample) * (# channels) bytes in frame
      55             :  *
      56             :  * Finally, not all id CIN creation tools agree on the resolution of the
      57             :  * color palette, apparently. Some creation tools specify red, green, and
      58             :  * blue palette components in terms of 6-bit VGA color DAC values which
      59             :  * range from 0..63. Other tools specify the RGB components as full 8-bit
      60             :  * values that range from 0..255. Since there are no markers in the file to
      61             :  * differentiate between the two variants, this demuxer uses the following
      62             :  * heuristic:
      63             :  *   - load the 768 palette bytes from disk
      64             :  *   - assume that they will need to be shifted left by 2 bits to
      65             :  *     transform them from 6-bit values to 8-bit values
      66             :  *   - scan through all 768 palette bytes
      67             :  *     - if any bytes exceed 63, do not shift the bytes at all before
      68             :  *       transmitting them to the video decoder
      69             :  */
      70             : 
      71             : #include "libavutil/channel_layout.h"
      72             : #include "libavutil/imgutils.h"
      73             : #include "libavutil/intreadwrite.h"
      74             : #include "avformat.h"
      75             : #include "internal.h"
      76             : 
      77             : #define HUFFMAN_TABLE_SIZE (64 * 1024)
      78             : #define IDCIN_FPS 14
      79             : 
      80             : typedef struct IdcinDemuxContext {
      81             :     int video_stream_index;
      82             :     int audio_stream_index;
      83             :     int audio_chunk_size1;
      84             :     int audio_chunk_size2;
      85             :     int block_align;
      86             : 
      87             :     /* demux state variables */
      88             :     int current_audio_chunk;
      89             :     int next_chunk_is_video;
      90             :     int audio_present;
      91             :     int64_t first_pkt_pos;
      92             : } IdcinDemuxContext;
      93             : 
      94        6130 : static int idcin_probe(AVProbeData *p)
      95             : {
      96             :     unsigned int number, sample_rate;
      97             :     unsigned int w, h;
      98             :     int i;
      99             : 
     100             :     /*
     101             :      * This is what you could call a "probabilistic" file check: id CIN
     102             :      * files don't have a definite file signature. In lieu of such a marker,
     103             :      * perform sanity checks on the 5 32-bit header fields:
     104             :      *  width, height: greater than 0, less than or equal to 1024
     105             :      * audio sample rate: greater than or equal to 8000, less than or
     106             :      *  equal to 48000, or 0 for no audio
     107             :      * audio sample width (bytes/sample): 0 for no audio, or 1 or 2
     108             :      * audio channels: 0 for no audio, or 1 or 2
     109             :      */
     110             : 
     111             :     /* check we have enough data to do all checks, otherwise the
     112             :        0-padding may cause a wrong recognition */
     113        6130 :     if (p->buf_size < 20 + HUFFMAN_TABLE_SIZE + 12)
     114        5678 :         return 0;
     115             : 
     116             :     /* check the video width */
     117         452 :     w = AV_RL32(&p->buf[0]);
     118         452 :     if ((w == 0) || (w > 1024))
     119         451 :        return 0;
     120             : 
     121             :     /* check the video height */
     122           1 :     h = AV_RL32(&p->buf[4]);
     123           1 :     if ((h == 0) || (h > 1024))
     124           0 :        return 0;
     125             : 
     126             :     /* check the audio sample rate */
     127           1 :     sample_rate = AV_RL32(&p->buf[8]);
     128           1 :     if (sample_rate && (sample_rate < 8000 || sample_rate > 48000))
     129           0 :         return 0;
     130             : 
     131             :     /* check the audio bytes/sample */
     132           1 :     number = AV_RL32(&p->buf[12]);
     133           1 :     if (number > 2 || sample_rate && !number)
     134           0 :         return 0;
     135             : 
     136             :     /* check the audio channels */
     137           1 :     number = AV_RL32(&p->buf[16]);
     138           1 :     if (number > 2 || sample_rate && !number)
     139           0 :         return 0;
     140             : 
     141           1 :     i = 20 + HUFFMAN_TABLE_SIZE;
     142           1 :     if (AV_RL32(&p->buf[i]) == 1)
     143           1 :         i += 768;
     144             : 
     145           1 :     if (i+12 > p->buf_size || AV_RL32(&p->buf[i+8]) != w*h)
     146           0 :         return 1;
     147             : 
     148             :     /* return half certainty since this check is a bit sketchy */
     149           1 :     return AVPROBE_SCORE_EXTENSION;
     150             : }
     151             : 
     152           1 : static int idcin_read_header(AVFormatContext *s)
     153             : {
     154           1 :     AVIOContext *pb = s->pb;
     155           1 :     IdcinDemuxContext *idcin = s->priv_data;
     156             :     AVStream *st;
     157             :     unsigned int width, height;
     158             :     unsigned int sample_rate, bytes_per_sample, channels;
     159             :     int ret;
     160             : 
     161             :     /* get the 5 header parameters */
     162           1 :     width = avio_rl32(pb);
     163           1 :     height = avio_rl32(pb);
     164           1 :     sample_rate = avio_rl32(pb);
     165           1 :     bytes_per_sample = avio_rl32(pb);
     166           1 :     channels = avio_rl32(pb);
     167             : 
     168           1 :     if (s->pb->eof_reached) {
     169           0 :         av_log(s, AV_LOG_ERROR, "incomplete header\n");
     170           0 :         return s->pb->error ? s->pb->error : AVERROR_EOF;
     171             :     }
     172             : 
     173           1 :     if (av_image_check_size(width, height, 0, s) < 0)
     174           0 :         return AVERROR_INVALIDDATA;
     175           1 :     if (sample_rate > 0) {
     176           1 :         if (sample_rate < 14 || sample_rate > INT_MAX) {
     177           0 :             av_log(s, AV_LOG_ERROR, "invalid sample rate: %u\n", sample_rate);
     178           0 :             return AVERROR_INVALIDDATA;
     179             :         }
     180           1 :         if (bytes_per_sample < 1 || bytes_per_sample > 2) {
     181           0 :             av_log(s, AV_LOG_ERROR, "invalid bytes per sample: %u\n",
     182             :                    bytes_per_sample);
     183           0 :             return AVERROR_INVALIDDATA;
     184             :         }
     185           1 :         if (channels < 1 || channels > 2) {
     186           0 :             av_log(s, AV_LOG_ERROR, "invalid channels: %u\n", channels);
     187           0 :             return AVERROR_INVALIDDATA;
     188             :         }
     189           1 :         idcin->audio_present = 1;
     190             :     } else {
     191             :         /* if sample rate is 0, assume no audio */
     192           0 :         idcin->audio_present = 0;
     193             :     }
     194             : 
     195           1 :     st = avformat_new_stream(s, NULL);
     196           1 :     if (!st)
     197           0 :         return AVERROR(ENOMEM);
     198           1 :     avpriv_set_pts_info(st, 33, 1, IDCIN_FPS);
     199           1 :     st->start_time = 0;
     200           1 :     idcin->video_stream_index = st->index;
     201           1 :     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     202           1 :     st->codecpar->codec_id = AV_CODEC_ID_IDCIN;
     203           1 :     st->codecpar->codec_tag = 0;  /* no fourcc */
     204           1 :     st->codecpar->width = width;
     205           1 :     st->codecpar->height = height;
     206             : 
     207             :     /* load up the Huffman tables into extradata */
     208           1 :     if ((ret = ff_get_extradata(s, st->codecpar, pb, HUFFMAN_TABLE_SIZE)) < 0)
     209           0 :         return ret;
     210             : 
     211           1 :     if (idcin->audio_present) {
     212           1 :         idcin->audio_present = 1;
     213           1 :         st = avformat_new_stream(s, NULL);
     214           1 :         if (!st)
     215           0 :             return AVERROR(ENOMEM);
     216           1 :         avpriv_set_pts_info(st, 63, 1, sample_rate);
     217           1 :         st->start_time = 0;
     218           1 :         idcin->audio_stream_index = st->index;
     219           1 :         st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     220           1 :         st->codecpar->codec_tag = 1;
     221           1 :         st->codecpar->channels = channels;
     222           1 :         st->codecpar->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO :
     223             :                                                       AV_CH_LAYOUT_MONO;
     224           1 :         st->codecpar->sample_rate = sample_rate;
     225           1 :         st->codecpar->bits_per_coded_sample = bytes_per_sample * 8;
     226           1 :         st->codecpar->bit_rate = sample_rate * bytes_per_sample * 8 * channels;
     227           1 :         st->codecpar->block_align = idcin->block_align = bytes_per_sample * channels;
     228           1 :         if (bytes_per_sample == 1)
     229           0 :             st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
     230             :         else
     231           1 :             st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
     232             : 
     233           1 :         if (sample_rate % 14 != 0) {
     234           0 :             idcin->audio_chunk_size1 = (sample_rate / 14) *
     235           0 :             bytes_per_sample * channels;
     236           0 :             idcin->audio_chunk_size2 = (sample_rate / 14 + 1) *
     237           0 :                 bytes_per_sample * channels;
     238             :         } else {
     239           1 :             idcin->audio_chunk_size1 = idcin->audio_chunk_size2 =
     240           1 :                 (sample_rate / 14) * bytes_per_sample * channels;
     241             :         }
     242           1 :         idcin->current_audio_chunk = 0;
     243             :     }
     244             : 
     245           1 :     idcin->next_chunk_is_video = 1;
     246           1 :     idcin->first_pkt_pos = avio_tell(s->pb);
     247             : 
     248           1 :     return 0;
     249             : }
     250             : 
     251         105 : static int idcin_read_packet(AVFormatContext *s,
     252             :                              AVPacket *pkt)
     253             : {
     254             :     int ret;
     255             :     unsigned int command;
     256             :     unsigned int chunk_size;
     257         105 :     IdcinDemuxContext *idcin = s->priv_data;
     258         105 :     AVIOContext *pb = s->pb;
     259             :     int i;
     260             :     int palette_scale;
     261             :     unsigned char r, g, b;
     262             :     unsigned char palette_buffer[768];
     263             :     uint32_t palette[256];
     264             : 
     265         105 :     if (avio_feof(s->pb))
     266           0 :         return s->pb->error ? s->pb->error : AVERROR_EOF;
     267             : 
     268         105 :     if (idcin->next_chunk_is_video) {
     269          53 :         command = avio_rl32(pb);
     270          53 :         if (command == 2) {
     271           0 :             return AVERROR(EIO);
     272          53 :         } else if (command == 1) {
     273             :             /* trigger a palette change */
     274           1 :             ret = avio_read(pb, palette_buffer, 768);
     275           1 :             if (ret < 0) {
     276           0 :                 return ret;
     277           1 :             } else if (ret != 768) {
     278           0 :                 av_log(s, AV_LOG_ERROR, "incomplete packet\n");
     279           0 :                 return AVERROR(EIO);
     280             :             }
     281             :             /* scale the palette as necessary */
     282           1 :             palette_scale = 2;
     283           1 :             for (i = 0; i < 768; i++)
     284           1 :                 if (palette_buffer[i] > 63) {
     285           1 :                     palette_scale = 0;
     286           1 :                     break;
     287             :                 }
     288             : 
     289         257 :             for (i = 0; i < 256; i++) {
     290         256 :                 r = palette_buffer[i * 3    ] << palette_scale;
     291         256 :                 g = palette_buffer[i * 3 + 1] << palette_scale;
     292         256 :                 b = palette_buffer[i * 3 + 2] << palette_scale;
     293         256 :                 palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
     294         256 :                 if (palette_scale == 2)
     295           0 :                     palette[i] |= palette[i] >> 6 & 0x30303;
     296             :             }
     297             :         }
     298             : 
     299          53 :         if (s->pb->eof_reached) {
     300           0 :             av_log(s, AV_LOG_ERROR, "incomplete packet\n");
     301           0 :             return s->pb->error ? s->pb->error : AVERROR_EOF;
     302             :         }
     303          53 :         chunk_size = avio_rl32(pb);
     304          53 :         if (chunk_size < 4 || chunk_size > INT_MAX - 4) {
     305           0 :             av_log(s, AV_LOG_ERROR, "invalid chunk size: %u\n", chunk_size);
     306           0 :             return AVERROR_INVALIDDATA;
     307             :         }
     308             :         /* skip the number of decoded bytes (always equal to width * height) */
     309          53 :         avio_skip(pb, 4);
     310          53 :         chunk_size -= 4;
     311          53 :         ret= av_get_packet(pb, pkt, chunk_size);
     312          53 :         if (ret < 0)
     313           0 :             return ret;
     314          53 :         else if (ret != chunk_size) {
     315           1 :             av_log(s, AV_LOG_ERROR, "incomplete packet\n");
     316           1 :             av_packet_unref(pkt);
     317           1 :             return AVERROR(EIO);
     318             :         }
     319          52 :         if (command == 1) {
     320             :             uint8_t *pal;
     321             : 
     322           1 :             pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
     323             :                                           AVPALETTE_SIZE);
     324           1 :             if (!pal) {
     325           0 :                 av_packet_unref(pkt);
     326           0 :                 return AVERROR(ENOMEM);
     327             :             }
     328           1 :             memcpy(pal, palette, AVPALETTE_SIZE);
     329           1 :             pkt->flags |= AV_PKT_FLAG_KEY;
     330             :         }
     331          52 :         pkt->stream_index = idcin->video_stream_index;
     332          52 :         pkt->duration     = 1;
     333             :     } else {
     334             :         /* send out the audio chunk */
     335          52 :         if (idcin->current_audio_chunk)
     336          26 :             chunk_size = idcin->audio_chunk_size2;
     337             :         else
     338          26 :             chunk_size = idcin->audio_chunk_size1;
     339          52 :         ret= av_get_packet(pb, pkt, chunk_size);
     340          52 :         if (ret < 0)
     341           0 :             return ret;
     342          52 :         pkt->stream_index = idcin->audio_stream_index;
     343          52 :         pkt->duration     = chunk_size / idcin->block_align;
     344             : 
     345          52 :         idcin->current_audio_chunk ^= 1;
     346             :     }
     347             : 
     348         104 :     if (idcin->audio_present)
     349         104 :         idcin->next_chunk_is_video ^= 1;
     350             : 
     351         104 :     return 0;
     352             : }
     353             : 
     354           0 : static int idcin_read_seek(AVFormatContext *s, int stream_index,
     355             :                            int64_t timestamp, int flags)
     356             : {
     357           0 :     IdcinDemuxContext *idcin = s->priv_data;
     358             : 
     359           0 :     if (idcin->first_pkt_pos > 0) {
     360           0 :         int64_t ret = avio_seek(s->pb, idcin->first_pkt_pos, SEEK_SET);
     361           0 :         if (ret < 0)
     362           0 :             return ret;
     363           0 :         ff_update_cur_dts(s, s->streams[idcin->video_stream_index], 0);
     364           0 :         idcin->next_chunk_is_video = 1;
     365           0 :         idcin->current_audio_chunk = 0;
     366           0 :         return 0;
     367             :     }
     368           0 :     return -1;
     369             : }
     370             : 
     371             : AVInputFormat ff_idcin_demuxer = {
     372             :     .name           = "idcin",
     373             :     .long_name      = NULL_IF_CONFIG_SMALL("id Cinematic"),
     374             :     .priv_data_size = sizeof(IdcinDemuxContext),
     375             :     .read_probe     = idcin_probe,
     376             :     .read_header    = idcin_read_header,
     377             :     .read_packet    = idcin_read_packet,
     378             :     .read_seek      = idcin_read_seek,
     379             :     .flags          = AVFMT_NO_BYTE_SEEK,
     380             : };

Generated by: LCOV version 1.13