LCOV - code coverage report
Current view: top level - libavformat - ipmovie.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 265 382 69.4 %
Date: 2017-12-16 13:57:32 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Interplay MVE 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             :  * Interplay MVE file demuxer
      25             :  * by Mike Melanson (melanson@pcisys.net)
      26             :  * For more information regarding the Interplay MVE file format, visit:
      27             :  *   http://www.pcisys.net/~melanson/codecs/
      28             :  * The aforementioned site also contains a command line utility for parsing
      29             :  * IP MVE files so that you can get a good idea of the typical structure of
      30             :  * such files. This demuxer is not the best example to use if you are trying
      31             :  * to write your own as it uses a rather roundabout approach for splitting
      32             :  * up and sending out the chunks.
      33             :  */
      34             : 
      35             : #include "libavutil/channel_layout.h"
      36             : #include "libavutil/intreadwrite.h"
      37             : #include "avformat.h"
      38             : #include "internal.h"
      39             : 
      40             : #define CHUNK_PREAMBLE_SIZE 4
      41             : #define OPCODE_PREAMBLE_SIZE 4
      42             : 
      43             : #define CHUNK_INIT_AUDIO   0x0000
      44             : #define CHUNK_AUDIO_ONLY   0x0001
      45             : #define CHUNK_INIT_VIDEO   0x0002
      46             : #define CHUNK_VIDEO        0x0003
      47             : #define CHUNK_SHUTDOWN     0x0004
      48             : #define CHUNK_END          0x0005
      49             : /* these last types are used internally */
      50             : #define CHUNK_DONE         0xFFFC
      51             : #define CHUNK_NOMEM        0xFFFD
      52             : #define CHUNK_EOF          0xFFFE
      53             : #define CHUNK_BAD          0xFFFF
      54             : 
      55             : #define OPCODE_END_OF_STREAM           0x00
      56             : #define OPCODE_END_OF_CHUNK            0x01
      57             : #define OPCODE_CREATE_TIMER            0x02
      58             : #define OPCODE_INIT_AUDIO_BUFFERS      0x03
      59             : #define OPCODE_START_STOP_AUDIO        0x04
      60             : #define OPCODE_INIT_VIDEO_BUFFERS      0x05
      61             : #define OPCODE_VIDEO_DATA_06           0x06
      62             : #define OPCODE_SEND_BUFFER             0x07
      63             : #define OPCODE_AUDIO_FRAME             0x08
      64             : #define OPCODE_SILENCE_FRAME           0x09
      65             : #define OPCODE_INIT_VIDEO_MODE         0x0A
      66             : #define OPCODE_CREATE_GRADIENT         0x0B
      67             : #define OPCODE_SET_PALETTE             0x0C
      68             : #define OPCODE_SET_PALETTE_COMPRESSED  0x0D
      69             : #define OPCODE_SET_SKIP_MAP            0x0E
      70             : #define OPCODE_SET_DECODING_MAP        0x0F
      71             : #define OPCODE_VIDEO_DATA_10           0x10
      72             : #define OPCODE_VIDEO_DATA_11           0x11
      73             : #define OPCODE_UNKNOWN_12              0x12
      74             : #define OPCODE_UNKNOWN_13              0x13
      75             : #define OPCODE_UNKNOWN_14              0x14
      76             : #define OPCODE_UNKNOWN_15              0x15
      77             : 
      78             : #define PALETTE_COUNT 256
      79             : 
      80             : typedef struct IPMVEContext {
      81             :     AVFormatContext *avf;
      82             :     unsigned char *buf;
      83             :     int buf_size;
      84             : 
      85             :     uint64_t frame_pts_inc;
      86             : 
      87             :     unsigned int video_bpp;
      88             :     unsigned int video_width;
      89             :     unsigned int video_height;
      90             :     int64_t video_pts;
      91             :     uint32_t     palette[256];
      92             :     int          has_palette;
      93             :     int          changed;
      94             :     uint8_t      send_buffer;
      95             :     uint8_t      frame_format;
      96             : 
      97             :     unsigned int audio_bits;
      98             :     unsigned int audio_channels;
      99             :     unsigned int audio_sample_rate;
     100             :     enum AVCodecID audio_type;
     101             :     unsigned int audio_frame_count;
     102             : 
     103             :     int video_stream_index;
     104             :     int audio_stream_index;
     105             : 
     106             :     int64_t audio_chunk_offset;
     107             :     int audio_chunk_size;
     108             :     int64_t video_chunk_offset;
     109             :     int video_chunk_size;
     110             :     int64_t skip_map_chunk_offset;
     111             :     int skip_map_chunk_size;
     112             :     int64_t decode_map_chunk_offset;
     113             :     int decode_map_chunk_size;
     114             : 
     115             :     int64_t next_chunk_offset;
     116             : 
     117             : } IPMVEContext;
     118             : 
     119         933 : static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
     120             :     AVPacket *pkt) {
     121             : 
     122             :     int chunk_type;
     123             : 
     124         933 :     if (s->audio_chunk_offset && s->audio_channels && s->audio_bits) {
     125         327 :         if (s->audio_type == AV_CODEC_ID_NONE) {
     126           0 :             av_log(s->avf, AV_LOG_ERROR, "Can not read audio packet before"
     127             :                    "audio codec is known\n");
     128           0 :                 return CHUNK_BAD;
     129             :         }
     130             : 
     131             :         /* adjust for PCM audio by skipping chunk header */
     132         327 :         if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM) {
     133           0 :             s->audio_chunk_offset += 6;
     134           0 :             s->audio_chunk_size -= 6;
     135             :         }
     136             : 
     137         327 :         avio_seek(pb, s->audio_chunk_offset, SEEK_SET);
     138         327 :         s->audio_chunk_offset = 0;
     139             : 
     140         327 :         if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
     141           0 :             return CHUNK_EOF;
     142             : 
     143         327 :         pkt->stream_index = s->audio_stream_index;
     144         327 :         pkt->pts = s->audio_frame_count;
     145             : 
     146             :         /* audio frame maintenance */
     147         327 :         if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM)
     148           0 :             s->audio_frame_count +=
     149           0 :             (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
     150             :         else
     151         654 :             s->audio_frame_count +=
     152         327 :                 (s->audio_chunk_size - 6 - s->audio_channels) / s->audio_channels;
     153             : 
     154         327 :         av_log(s->avf, AV_LOG_TRACE, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
     155             :                 pkt->pts, s->audio_frame_count);
     156             : 
     157         327 :         chunk_type = CHUNK_VIDEO;
     158             : 
     159         606 :     } else if (s->frame_format) {
     160             : 
     161             :         /* send the frame format, decode map, the video data, skip map, and the send_buffer flag together */
     162             : 
     163         270 :         if (av_new_packet(pkt, 8 + s->decode_map_chunk_size + s->video_chunk_size + s->skip_map_chunk_size))
     164           0 :             return CHUNK_NOMEM;
     165             : 
     166         270 :         if (s->has_palette) {
     167             :             uint8_t *pal;
     168             : 
     169           2 :             pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
     170             :                                           AVPALETTE_SIZE);
     171           2 :             if (pal) {
     172           2 :                 memcpy(pal, s->palette, AVPALETTE_SIZE);
     173           2 :                 s->has_palette = 0;
     174             :             }
     175             :         }
     176             : 
     177         270 :         if (s->changed) {
     178           3 :             ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height);
     179           3 :             s->changed = 0;
     180             :         }
     181             : 
     182         270 :         AV_WL8(pkt->data, s->frame_format);
     183         270 :         AV_WL8(pkt->data + 1, s->send_buffer);
     184         270 :         AV_WL16(pkt->data + 2, s->video_chunk_size);
     185         270 :         AV_WL16(pkt->data + 4, s->decode_map_chunk_size);
     186         270 :         AV_WL16(pkt->data + 6, s->skip_map_chunk_size);
     187             : 
     188         270 :         s->frame_format = 0;
     189         270 :         s->send_buffer = 0;
     190             : 
     191         270 :         pkt->pos = s->video_chunk_offset;
     192         270 :         avio_seek(pb, s->video_chunk_offset, SEEK_SET);
     193         270 :         s->video_chunk_offset = 0;
     194             : 
     195         540 :         if (avio_read(pb, pkt->data + 8, s->video_chunk_size) !=
     196         270 :             s->video_chunk_size) {
     197           0 :             av_packet_unref(pkt);
     198           0 :             return CHUNK_EOF;
     199             :         }
     200             : 
     201         270 :         if (s->decode_map_chunk_size) {
     202         270 :             pkt->pos = s->decode_map_chunk_offset;
     203         270 :             avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
     204         270 :             s->decode_map_chunk_offset = 0;
     205             : 
     206         540 :             if (avio_read(pb, pkt->data + 8 + s->video_chunk_size,
     207         270 :                 s->decode_map_chunk_size) != s->decode_map_chunk_size) {
     208           0 :                 av_packet_unref(pkt);
     209           0 :                 return CHUNK_EOF;
     210             :             }
     211             :         }
     212             : 
     213         270 :         if (s->skip_map_chunk_size) {
     214           0 :             pkt->pos = s->skip_map_chunk_offset;
     215           0 :             avio_seek(pb, s->skip_map_chunk_offset, SEEK_SET);
     216           0 :             s->skip_map_chunk_offset = 0;
     217             : 
     218           0 :             if (avio_read(pb, pkt->data + 8 + s->video_chunk_size + s->decode_map_chunk_size,
     219           0 :                 s->skip_map_chunk_size) != s->skip_map_chunk_size) {
     220           0 :                 av_packet_unref(pkt);
     221           0 :                 return CHUNK_EOF;
     222             :             }
     223             :         }
     224             : 
     225         270 :         s->video_chunk_size = 0;
     226         270 :         s->decode_map_chunk_size = 0;
     227         270 :         s->skip_map_chunk_size = 0;
     228             : 
     229         270 :         pkt->stream_index = s->video_stream_index;
     230         270 :         pkt->pts = s->video_pts;
     231             : 
     232         270 :         av_log(s->avf, AV_LOG_TRACE, "sending video frame with pts %"PRId64"\n", pkt->pts);
     233             : 
     234         270 :         s->video_pts += s->frame_pts_inc;
     235             : 
     236         270 :         chunk_type = CHUNK_VIDEO;
     237             : 
     238             :     } else {
     239             : 
     240         336 :         avio_seek(pb, s->next_chunk_offset, SEEK_SET);
     241         336 :         chunk_type = CHUNK_DONE;
     242             : 
     243             :     }
     244             : 
     245         933 :     return chunk_type;
     246             : }
     247             : 
     248           3 : static int init_audio(AVFormatContext *s)
     249             : {
     250           3 :     IPMVEContext *ipmovie = s->priv_data;
     251           3 :     AVStream *st = avformat_new_stream(s, NULL);
     252           3 :     if (!st)
     253           0 :         return AVERROR(ENOMEM);
     254           3 :     avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
     255           3 :     ipmovie->audio_stream_index = st->index;
     256           3 :     st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     257           3 :     st->codecpar->codec_id = ipmovie->audio_type;
     258           3 :     st->codecpar->codec_tag = 0;  /* no tag */
     259           3 :     st->codecpar->channels = ipmovie->audio_channels;
     260           3 :     st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO :
     261             :                                                             AV_CH_LAYOUT_STEREO;
     262           3 :     st->codecpar->sample_rate = ipmovie->audio_sample_rate;
     263           3 :     st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
     264           6 :     st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
     265           3 :         st->codecpar->bits_per_coded_sample;
     266           3 :     if (st->codecpar->codec_id == AV_CODEC_ID_INTERPLAY_DPCM)
     267           3 :         st->codecpar->bit_rate /= 2;
     268           3 :     st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
     269             : 
     270           3 :     return 0;
     271             : }
     272             : 
     273             : /* This function loads and processes a single chunk in an IP movie file.
     274             :  * It returns the type of chunk that was processed. */
     275         606 : static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
     276             :     AVPacket *pkt)
     277             : {
     278             :     unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
     279             :     int chunk_type;
     280             :     int chunk_size;
     281             :     unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
     282             :     unsigned char opcode_type;
     283             :     unsigned char opcode_version;
     284             :     int opcode_size;
     285             :     unsigned char scratch[1024];
     286             :     int i, j;
     287             :     int first_color, last_color;
     288             :     int audio_flags;
     289             :     unsigned char r, g, b;
     290             :     unsigned int width, height;
     291             : 
     292             :     /* see if there are any pending packets */
     293         606 :     chunk_type = load_ipmovie_packet(s, pb, pkt);
     294         606 :     if (chunk_type != CHUNK_DONE)
     295         270 :         return chunk_type;
     296             : 
     297             :     /* read the next chunk, wherever the file happens to be pointing */
     298         336 :     if (avio_feof(pb))
     299           0 :         return CHUNK_EOF;
     300         336 :     if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
     301             :         CHUNK_PREAMBLE_SIZE)
     302           0 :         return CHUNK_BAD;
     303         336 :     chunk_size = AV_RL16(&chunk_preamble[0]);
     304         336 :     chunk_type = AV_RL16(&chunk_preamble[2]);
     305             : 
     306         336 :     av_log(s->avf, AV_LOG_TRACE, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
     307             : 
     308         336 :     switch (chunk_type) {
     309             : 
     310           3 :     case CHUNK_INIT_AUDIO:
     311           3 :         av_log(s->avf, AV_LOG_TRACE, "initialize audio\n");
     312           3 :         break;
     313             : 
     314          57 :     case CHUNK_AUDIO_ONLY:
     315          57 :         av_log(s->avf, AV_LOG_TRACE, "audio only\n");
     316          57 :         break;
     317             : 
     318           3 :     case CHUNK_INIT_VIDEO:
     319           3 :         av_log(s->avf, AV_LOG_TRACE, "initialize video\n");
     320           3 :         break;
     321             : 
     322         273 :     case CHUNK_VIDEO:
     323         273 :         av_log(s->avf, AV_LOG_TRACE, "video (and audio)\n");
     324         273 :         break;
     325             : 
     326           0 :     case CHUNK_SHUTDOWN:
     327           0 :         av_log(s->avf, AV_LOG_TRACE, "shutdown\n");
     328           0 :         break;
     329             : 
     330           0 :     case CHUNK_END:
     331           0 :         av_log(s->avf, AV_LOG_TRACE, "end\n");
     332           0 :         break;
     333             : 
     334           0 :     default:
     335           0 :         av_log(s->avf, AV_LOG_TRACE, "invalid chunk\n");
     336           0 :         chunk_type = CHUNK_BAD;
     337           0 :         break;
     338             : 
     339             :     }
     340             : 
     341        3036 :     while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
     342             : 
     343             :         /* read the next chunk, wherever the file happens to be pointing */
     344        2367 :         if (avio_feof(pb)) {
     345           3 :             chunk_type = CHUNK_EOF;
     346           3 :             break;
     347             :         }
     348        2364 :         if (avio_read(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
     349             :             CHUNK_PREAMBLE_SIZE) {
     350           0 :             chunk_type = CHUNK_BAD;
     351           0 :             break;
     352             :         }
     353             : 
     354        2364 :         opcode_size = AV_RL16(&opcode_preamble[0]);
     355        2364 :         opcode_type = opcode_preamble[2];
     356        2364 :         opcode_version = opcode_preamble[3];
     357             : 
     358        2364 :         chunk_size -= OPCODE_PREAMBLE_SIZE;
     359        2364 :         chunk_size -= opcode_size;
     360        2364 :         if (chunk_size < 0) {
     361           0 :             av_log(s->avf, AV_LOG_TRACE, "chunk_size countdown just went negative\n");
     362           0 :             chunk_type = CHUNK_BAD;
     363           0 :             break;
     364             :         }
     365             : 
     366        2364 :         av_log(s->avf, AV_LOG_TRACE, "  opcode type %02X, version %d, 0x%04X bytes: ",
     367             :                 opcode_type, opcode_version, opcode_size);
     368        2364 :         switch (opcode_type) {
     369             : 
     370           0 :         case OPCODE_END_OF_STREAM:
     371           0 :             av_log(s->avf, AV_LOG_TRACE, "end of stream\n");
     372           0 :             avio_skip(pb, opcode_size);
     373           0 :             break;
     374             : 
     375         333 :         case OPCODE_END_OF_CHUNK:
     376         333 :             av_log(s->avf, AV_LOG_TRACE, "end of chunk\n");
     377         333 :             avio_skip(pb, opcode_size);
     378         333 :             break;
     379             : 
     380           3 :         case OPCODE_CREATE_TIMER:
     381           3 :             av_log(s->avf, AV_LOG_TRACE, "create timer\n");
     382           3 :             if ((opcode_version > 0) || (opcode_size != 6)) {
     383           0 :                 av_log(s->avf, AV_LOG_TRACE, "bad create_timer opcode\n");
     384           0 :                 chunk_type = CHUNK_BAD;
     385           0 :                 break;
     386             :             }
     387           3 :             if (avio_read(pb, scratch, opcode_size) !=
     388             :                 opcode_size) {
     389           0 :                 chunk_type = CHUNK_BAD;
     390           0 :                 break;
     391             :             }
     392           3 :             s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]);
     393           3 :             break;
     394             : 
     395           3 :         case OPCODE_INIT_AUDIO_BUFFERS:
     396           3 :             av_log(s->avf, AV_LOG_TRACE, "initialize audio buffers\n");
     397           3 :             if (opcode_version > 1 || opcode_size > 10 || opcode_size < 6) {
     398           0 :                 av_log(s->avf, AV_LOG_TRACE, "bad init_audio_buffers opcode\n");
     399           0 :                 chunk_type = CHUNK_BAD;
     400           0 :                 break;
     401             :             }
     402           3 :             if (avio_read(pb, scratch, opcode_size) !=
     403             :                 opcode_size) {
     404           0 :                 chunk_type = CHUNK_BAD;
     405           0 :                 break;
     406             :             }
     407           3 :             s->audio_sample_rate = AV_RL16(&scratch[4]);
     408           3 :             audio_flags = AV_RL16(&scratch[2]);
     409             :             /* bit 0 of the flags: 0 = mono, 1 = stereo */
     410           3 :             s->audio_channels = (audio_flags & 1) + 1;
     411             :             /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
     412           3 :             s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
     413             :             /* bit 2 indicates compressed audio in version 1 opcode */
     414           3 :             if ((opcode_version == 1) && (audio_flags & 0x4))
     415           3 :                 s->audio_type = AV_CODEC_ID_INTERPLAY_DPCM;
     416           0 :             else if (s->audio_bits == 16)
     417           0 :                 s->audio_type = AV_CODEC_ID_PCM_S16LE;
     418             :             else
     419           0 :                 s->audio_type = AV_CODEC_ID_PCM_U8;
     420           6 :             av_log(s->avf, AV_LOG_TRACE, "audio: %d bits, %d Hz, %s, %s format\n",
     421             :                     s->audio_bits, s->audio_sample_rate,
     422           3 :                     (s->audio_channels == 2) ? "stereo" : "mono",
     423           3 :                     (s->audio_type == AV_CODEC_ID_INTERPLAY_DPCM) ?
     424             :                     "Interplay audio" : "PCM");
     425           3 :             break;
     426             : 
     427         270 :         case OPCODE_START_STOP_AUDIO:
     428         270 :             av_log(s->avf, AV_LOG_TRACE, "start/stop audio\n");
     429         270 :             avio_skip(pb, opcode_size);
     430         270 :             break;
     431             : 
     432           3 :         case OPCODE_INIT_VIDEO_BUFFERS:
     433           3 :             av_log(s->avf, AV_LOG_TRACE, "initialize video buffers\n");
     434           3 :             if ((opcode_version > 2) || (opcode_size > 8) || opcode_size < 4
     435           3 :                 || opcode_version == 2 && opcode_size < 8
     436             :             ) {
     437           0 :                 av_log(s->avf, AV_LOG_TRACE, "bad init_video_buffers opcode\n");
     438           0 :                 chunk_type = CHUNK_BAD;
     439           0 :                 break;
     440             :             }
     441           3 :             if (avio_read(pb, scratch, opcode_size) !=
     442             :                 opcode_size) {
     443           0 :                 chunk_type = CHUNK_BAD;
     444           0 :                 break;
     445             :             }
     446           3 :             width  = AV_RL16(&scratch[0]) * 8;
     447           3 :             height = AV_RL16(&scratch[2]) * 8;
     448           3 :             if (width != s->video_width) {
     449           3 :                 s->video_width = width;
     450           3 :                 s->changed++;
     451             :             }
     452           3 :             if (height != s->video_height) {
     453           3 :                 s->video_height = height;
     454           3 :                 s->changed++;
     455             :             }
     456           3 :             if (opcode_version < 2 || !AV_RL16(&scratch[6])) {
     457           2 :                 s->video_bpp = 8;
     458             :             } else {
     459           1 :                 s->video_bpp = 16;
     460             :             }
     461           3 :             av_log(s->avf, AV_LOG_TRACE, "video resolution: %d x %d\n",
     462             :                     s->video_width, s->video_height);
     463           3 :             break;
     464             : 
     465         273 :         case OPCODE_UNKNOWN_12:
     466             :         case OPCODE_UNKNOWN_13:
     467             :         case OPCODE_UNKNOWN_14:
     468             :         case OPCODE_UNKNOWN_15:
     469         273 :             av_log(s->avf, AV_LOG_TRACE, "unknown (but documented) opcode %02X\n", opcode_type);
     470         273 :             avio_skip(pb, opcode_size);
     471         273 :             break;
     472             : 
     473         270 :         case OPCODE_SEND_BUFFER:
     474         270 :             av_log(s->avf, AV_LOG_TRACE, "send buffer\n");
     475         270 :             avio_skip(pb, opcode_size);
     476         270 :             s->send_buffer = 1;
     477         270 :             break;
     478             : 
     479         330 :         case OPCODE_AUDIO_FRAME:
     480         330 :             av_log(s->avf, AV_LOG_TRACE, "audio frame\n");
     481             : 
     482             :             /* log position and move on for now */
     483         330 :             s->audio_chunk_offset = avio_tell(pb);
     484         330 :             s->audio_chunk_size = opcode_size;
     485         330 :             avio_skip(pb, opcode_size);
     486         330 :             break;
     487             : 
     488         329 :         case OPCODE_SILENCE_FRAME:
     489         329 :             av_log(s->avf, AV_LOG_TRACE, "silence frame\n");
     490         329 :             avio_skip(pb, opcode_size);
     491         329 :             break;
     492             : 
     493           3 :         case OPCODE_INIT_VIDEO_MODE:
     494           3 :             av_log(s->avf, AV_LOG_TRACE, "initialize video mode\n");
     495           3 :             avio_skip(pb, opcode_size);
     496           3 :             break;
     497             : 
     498           0 :         case OPCODE_CREATE_GRADIENT:
     499           0 :             av_log(s->avf, AV_LOG_TRACE, "create gradient\n");
     500           0 :             avio_skip(pb, opcode_size);
     501           0 :             break;
     502             : 
     503           2 :         case OPCODE_SET_PALETTE:
     504           2 :             av_log(s->avf, AV_LOG_TRACE, "set palette\n");
     505             :             /* check for the logical maximum palette size
     506             :              * (3 * 256 + 4 bytes) */
     507           2 :             if (opcode_size > 0x304 || opcode_size < 4) {
     508           0 :                 av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette opcode with invalid size\n");
     509           0 :                 chunk_type = CHUNK_BAD;
     510           0 :                 break;
     511             :             }
     512           2 :             if (avio_read(pb, scratch, opcode_size) != opcode_size) {
     513           0 :                 chunk_type = CHUNK_BAD;
     514           0 :                 break;
     515             :             }
     516             : 
     517             :             /* load the palette into internal data structure */
     518           2 :             first_color = AV_RL16(&scratch[0]);
     519           2 :             last_color = first_color + AV_RL16(&scratch[2]) - 1;
     520             :             /* sanity check (since they are 16 bit values) */
     521           2 :             if (   (first_color > 0xFF) || (last_color > 0xFF)
     522           2 :                 || (last_color - first_color + 1)*3 + 4 > opcode_size) {
     523           0 :                 av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
     524             :                     first_color, last_color);
     525           0 :                 chunk_type = CHUNK_BAD;
     526           0 :                 break;
     527             :             }
     528           2 :             j = 4;  /* offset of first palette data */
     529         510 :             for (i = first_color; i <= last_color; i++) {
     530             :                 /* the palette is stored as a 6-bit VGA palette, thus each
     531             :                  * component is shifted up to a 8-bit range */
     532         508 :                 r = scratch[j++] * 4;
     533         508 :                 g = scratch[j++] * 4;
     534         508 :                 b = scratch[j++] * 4;
     535         508 :                 s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
     536         508 :                 s->palette[i] |= s->palette[i] >> 6 & 0x30303;
     537             :             }
     538           2 :             s->has_palette = 1;
     539           2 :             break;
     540             : 
     541           0 :         case OPCODE_SET_PALETTE_COMPRESSED:
     542           0 :             av_log(s->avf, AV_LOG_TRACE, "set palette compressed\n");
     543           0 :             avio_skip(pb, opcode_size);
     544           0 :             break;
     545             : 
     546           0 :         case OPCODE_SET_SKIP_MAP:
     547           0 :             av_log(s->avf, AV_LOG_TRACE, "set skip map\n");
     548             : 
     549             :             /* log position and move on for now */
     550           0 :             s->skip_map_chunk_offset = avio_tell(pb);
     551           0 :             s->skip_map_chunk_size = opcode_size;
     552           0 :             avio_skip(pb, opcode_size);
     553           0 :             break;
     554             : 
     555         273 :         case OPCODE_SET_DECODING_MAP:
     556         273 :             av_log(s->avf, AV_LOG_TRACE, "set decoding map\n");
     557             : 
     558             :             /* log position and move on for now */
     559         273 :             s->decode_map_chunk_offset = avio_tell(pb);
     560         273 :             s->decode_map_chunk_size = opcode_size;
     561         273 :             avio_skip(pb, opcode_size);
     562         273 :             break;
     563             : 
     564           0 :         case OPCODE_VIDEO_DATA_06:
     565           0 :             av_log(s->avf, AV_LOG_TRACE, "set video data format 0x06\n");
     566           0 :             s->frame_format = 0x06;
     567             : 
     568             :             /* log position and move on for now */
     569           0 :             s->video_chunk_offset = avio_tell(pb);
     570           0 :             s->video_chunk_size = opcode_size;
     571           0 :             avio_skip(pb, opcode_size);
     572           0 :             break;
     573             : 
     574           0 :         case OPCODE_VIDEO_DATA_10:
     575           0 :             av_log(s->avf, AV_LOG_TRACE, "set video data format 0x10\n");
     576           0 :             s->frame_format = 0x10;
     577             : 
     578             :             /* log position and move on for now */
     579           0 :             s->video_chunk_offset = avio_tell(pb);
     580           0 :             s->video_chunk_size = opcode_size;
     581           0 :             avio_skip(pb, opcode_size);
     582           0 :             break;
     583             : 
     584         272 :         case OPCODE_VIDEO_DATA_11:
     585         272 :             av_log(s->avf, AV_LOG_TRACE, "set video data format 0x11\n");
     586         272 :             s->frame_format = 0x11;
     587             : 
     588             :             /* log position and move on for now */
     589         272 :             s->video_chunk_offset = avio_tell(pb);
     590         272 :             s->video_chunk_size = opcode_size;
     591         272 :             avio_skip(pb, opcode_size);
     592         272 :             break;
     593             : 
     594           0 :         default:
     595           0 :             av_log(s->avf, AV_LOG_TRACE, "*** unknown opcode type\n");
     596           0 :             chunk_type = CHUNK_BAD;
     597           0 :             break;
     598             : 
     599             :         }
     600             :     }
     601             : 
     602         336 :     if (s->avf->nb_streams == 1 && s->audio_type)
     603           0 :         init_audio(s->avf);
     604             : 
     605             :     /* make a note of where the stream is sitting */
     606         336 :     s->next_chunk_offset = avio_tell(pb);
     607             : 
     608             :     /* dispatch the first of any pending packets */
     609         336 :     if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
     610         327 :         chunk_type = load_ipmovie_packet(s, pb, pkt);
     611             : 
     612         336 :     return chunk_type;
     613             : }
     614             : 
     615             : static const char signature[] = "Interplay MVE File\x1A\0\x1A";
     616             : 
     617        6130 : static int ipmovie_probe(AVProbeData *p)
     618             : {
     619        6130 :     const uint8_t *b = p->buf;
     620        6130 :     const uint8_t *b_end = p->buf + p->buf_size - sizeof(signature);
     621             :     do {
     622   128133730 :         if (b[0] == signature[0] && memcmp(b, signature, sizeof(signature)) == 0)
     623           3 :             return AVPROBE_SCORE_MAX;
     624   128133727 :         b++;
     625   128133727 :     } while (b < b_end);
     626             : 
     627        6127 :     return 0;
     628             : }
     629             : 
     630           3 : static int ipmovie_read_header(AVFormatContext *s)
     631             : {
     632           3 :     IPMVEContext *ipmovie = s->priv_data;
     633           3 :     AVIOContext *pb = s->pb;
     634             :     AVPacket pkt;
     635             :     AVStream *st;
     636             :     unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
     637             :     int chunk_type, i;
     638             :     uint8_t signature_buffer[sizeof(signature)];
     639             : 
     640           3 :     ipmovie->avf = s;
     641             : 
     642           3 :     avio_read(pb, signature_buffer, sizeof(signature_buffer));
     643           3 :     while (memcmp(signature_buffer, signature, sizeof(signature))) {
     644           0 :         memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1);
     645           0 :         signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb);
     646           0 :         if (avio_feof(pb))
     647           0 :             return AVERROR_EOF;
     648             :     }
     649             :     /* initialize private context members */
     650           3 :     ipmovie->video_pts = ipmovie->audio_frame_count = 0;
     651           3 :     ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
     652           3 :     ipmovie->decode_map_chunk_offset = ipmovie->skip_map_chunk_offset = 0;
     653           3 :     ipmovie->decode_map_chunk_size = ipmovie->video_chunk_size =
     654           3 :     ipmovie->skip_map_chunk_size = 0;
     655           3 :     ipmovie->send_buffer = ipmovie->frame_format = 0;
     656             : 
     657             :     /* on the first read, this will position the stream at the first chunk */
     658           3 :     ipmovie->next_chunk_offset = avio_tell(pb) + 4;
     659             : 
     660         771 :     for (i = 0; i < 256; i++)
     661         768 :         ipmovie->palette[i] = 0xFFU << 24;
     662             : 
     663             :     /* process the first chunk which should be CHUNK_INIT_VIDEO */
     664           3 :     if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO)
     665           0 :         return AVERROR_INVALIDDATA;
     666             : 
     667             :     /* peek ahead to the next chunk-- if it is an init audio chunk, process
     668             :      * it; if it is the first video chunk, this is a silent file */
     669           3 :     if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
     670             :         CHUNK_PREAMBLE_SIZE)
     671           0 :         return AVERROR(EIO);
     672           3 :     chunk_type = AV_RL16(&chunk_preamble[2]);
     673           3 :     avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
     674             : 
     675           3 :     if (chunk_type == CHUNK_VIDEO)
     676           0 :         ipmovie->audio_type = AV_CODEC_ID_NONE;  /* no audio */
     677           3 :     else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO)
     678           0 :         return AVERROR_INVALIDDATA;
     679             : 
     680             :     /* initialize the stream decoders */
     681           3 :     st = avformat_new_stream(s, NULL);
     682           3 :     if (!st)
     683           0 :         return AVERROR(ENOMEM);
     684           3 :     avpriv_set_pts_info(st, 63, 1, 1000000);
     685           3 :     ipmovie->video_stream_index = st->index;
     686           3 :     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     687           3 :     st->codecpar->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO;
     688           3 :     st->codecpar->codec_tag = 0;  /* no fourcc */
     689           3 :     st->codecpar->width = ipmovie->video_width;
     690           3 :     st->codecpar->height = ipmovie->video_height;
     691           3 :     st->codecpar->bits_per_coded_sample = ipmovie->video_bpp;
     692             : 
     693           3 :     if (ipmovie->audio_type) {
     694           3 :         return init_audio(s);
     695             :     } else
     696           0 :        s->ctx_flags |= AVFMTCTX_NOHEADER;
     697             : 
     698           0 :     return 0;
     699             : }
     700             : 
     701         600 : static int ipmovie_read_packet(AVFormatContext *s,
     702             :                                AVPacket *pkt)
     703             : {
     704         600 :     IPMVEContext *ipmovie = s->priv_data;
     705         600 :     AVIOContext *pb = s->pb;
     706             :     int ret;
     707             : 
     708             :     for (;;) {
     709         600 :     ret = process_ipmovie_chunk(ipmovie, pb, pkt);
     710         600 :     if (ret == CHUNK_BAD)
     711           0 :         ret = AVERROR_INVALIDDATA;
     712         600 :     else if (ret == CHUNK_EOF)
     713           3 :         ret = AVERROR(EIO);
     714         597 :     else if (ret == CHUNK_NOMEM)
     715           0 :         ret = AVERROR(ENOMEM);
     716         597 :     else if (ret == CHUNK_END || ret == CHUNK_SHUTDOWN)
     717           0 :         ret = AVERROR_EOF;
     718         597 :     else if (ret == CHUNK_VIDEO)
     719         597 :         ret = 0;
     720           0 :     else if (ret == CHUNK_INIT_VIDEO || ret == CHUNK_INIT_AUDIO)
     721           0 :         continue;
     722             :     else
     723           0 :         continue;
     724             : 
     725        1200 :     return ret;
     726             :     }
     727             : }
     728             : 
     729             : AVInputFormat ff_ipmovie_demuxer = {
     730             :     .name           = "ipmovie",
     731             :     .long_name      = NULL_IF_CONFIG_SMALL("Interplay MVE"),
     732             :     .priv_data_size = sizeof(IPMVEContext),
     733             :     .read_probe     = ipmovie_probe,
     734             :     .read_header    = ipmovie_read_header,
     735             :     .read_packet    = ipmovie_read_packet,
     736             : };

Generated by: LCOV version 1.13