FFmpeg  4.0
mm.c
Go to the documentation of this file.
1 /*
2  * American Laser Games MM Format Demuxer
3  * Copyright (c) 2006 Peter Ross
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  * American Laser Games MM Format Demuxer
25  * by Peter Ross (pross@xvid.org)
26  *
27  * The MM format was used by IBM-PC ports of ALG's "arcade shooter" games,
28  * including Mad Dog McCree and Crime Patrol.
29  *
30  * Technical details here:
31  * http://wiki.multimedia.cx/index.php?title=American_Laser_Games_MM
32  */
33 
35 #include "libavutil/intreadwrite.h"
36 #include "avformat.h"
37 #include "internal.h"
38 
39 #define MM_PREAMBLE_SIZE 6
40 
41 #define MM_TYPE_HEADER 0x0
42 #define MM_TYPE_INTER 0x5
43 #define MM_TYPE_INTRA 0x8
44 #define MM_TYPE_INTRA_HH 0xc
45 #define MM_TYPE_INTER_HH 0xd
46 #define MM_TYPE_INTRA_HHV 0xe
47 #define MM_TYPE_INTER_HHV 0xf
48 #define MM_TYPE_AUDIO 0x15
49 #define MM_TYPE_PALETTE 0x31
50 
51 #define MM_HEADER_LEN_V 0x16 /* video only */
52 #define MM_HEADER_LEN_AV 0x18 /* video + audio */
53 
54 #define MM_PALETTE_COUNT 128
55 #define MM_PALETTE_SIZE (MM_PALETTE_COUNT*3)
56 
57 typedef struct MmDemuxContext {
58  unsigned int audio_pts, video_pts;
60 
61 static int probe(AVProbeData *p)
62 {
63  int len, type, fps, w, h;
65  return 0;
66  /* the first chunk is always the header */
67  if (AV_RL16(&p->buf[0]) != MM_TYPE_HEADER)
68  return 0;
69  len = AV_RL32(&p->buf[2]);
70  if (len != MM_HEADER_LEN_V && len != MM_HEADER_LEN_AV)
71  return 0;
72  fps = AV_RL16(&p->buf[8]);
73  w = AV_RL16(&p->buf[12]);
74  h = AV_RL16(&p->buf[14]);
75  if (!fps || fps > 60 || !w || w > 2048 || !h || h > 2048)
76  return 0;
77  type = AV_RL16(&p->buf[len]);
78  if (!type || type > 0x31)
79  return 0;
80 
81  /* only return half certainty since this check is a bit sketchy */
83 }
84 
86 {
87  MmDemuxContext *mm = s->priv_data;
88  AVIOContext *pb = s->pb;
89  AVStream *st;
90 
91  unsigned int type, length;
92  unsigned int frame_rate, width, height;
93 
94  type = avio_rl16(pb);
95  length = avio_rl32(pb);
96 
97  if (type != MM_TYPE_HEADER)
98  return AVERROR_INVALIDDATA;
99 
100  /* read header */
101  avio_rl16(pb); /* total number of chunks */
102  frame_rate = avio_rl16(pb);
103  avio_rl16(pb); /* ibm-pc video bios mode */
104  width = avio_rl16(pb);
105  height = avio_rl16(pb);
106  avio_skip(pb, length - 10); /* unknown data */
107 
108  /* video stream */
109  st = avformat_new_stream(s, NULL);
110  if (!st)
111  return AVERROR(ENOMEM);
114  st->codecpar->codec_tag = 0; /* no fourcc */
115  st->codecpar->width = width;
116  st->codecpar->height = height;
117  avpriv_set_pts_info(st, 64, 1, frame_rate);
118 
119  /* audio stream */
120  if (length == MM_HEADER_LEN_AV) {
121  st = avformat_new_stream(s, NULL);
122  if (!st)
123  return AVERROR(ENOMEM);
125  st->codecpar->codec_tag = 0; /* no fourcc */
127  st->codecpar->channels = 1;
129  st->codecpar->sample_rate = 8000;
130  avpriv_set_pts_info(st, 64, 1, 8000); /* 8000 hz */
131  }
132 
133  mm->audio_pts = 0;
134  mm->video_pts = 0;
135  return 0;
136 }
137 
139  AVPacket *pkt)
140 {
141  MmDemuxContext *mm = s->priv_data;
142  AVIOContext *pb = s->pb;
143  unsigned char preamble[MM_PREAMBLE_SIZE];
144  unsigned int type, length;
145 
146  while(1) {
147 
148  if (avio_read(pb, preamble, MM_PREAMBLE_SIZE) != MM_PREAMBLE_SIZE) {
149  return AVERROR(EIO);
150  }
151 
152  type = AV_RL16(&preamble[0]);
153  length = AV_RL16(&preamble[2]);
154 
155  switch(type) {
156  case MM_TYPE_PALETTE :
157  case MM_TYPE_INTER :
158  case MM_TYPE_INTRA :
159  case MM_TYPE_INTRA_HH :
160  case MM_TYPE_INTER_HH :
161  case MM_TYPE_INTRA_HHV :
162  case MM_TYPE_INTER_HHV :
163  /* output preamble + data */
164  if (av_new_packet(pkt, length + MM_PREAMBLE_SIZE))
165  return AVERROR(ENOMEM);
166  memcpy(pkt->data, preamble, MM_PREAMBLE_SIZE);
167  if (avio_read(pb, pkt->data + MM_PREAMBLE_SIZE, length) != length)
168  return AVERROR(EIO);
169  pkt->size = length + MM_PREAMBLE_SIZE;
170  pkt->stream_index = 0;
171  pkt->pts = mm->video_pts;
172  if (type!=MM_TYPE_PALETTE)
173  mm->video_pts++;
174  return 0;
175 
176  case MM_TYPE_AUDIO :
177  if (av_get_packet(s->pb, pkt, length)<0)
178  return AVERROR(ENOMEM);
179  pkt->stream_index = 1;
180  pkt->pts = mm->audio_pts++;
181  return 0;
182 
183  default :
184  av_log(s, AV_LOG_INFO, "unknown chunk type 0x%x\n", type);
185  avio_skip(pb, length);
186  }
187  }
188 }
189 
191  .name = "mm",
192  .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM"),
193  .priv_data_size = sizeof(MmDemuxContext),
194  .read_probe = probe,
197 };
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
Bytestream IO Context.
Definition: avio.h:161
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define MM_PREAMBLE_SIZE
Definition: mm.c:39
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4811
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3884
int size
Definition: avcodec.h:1431
#define AV_RL16
Definition: intreadwrite.h:42
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:331
AVInputFormat ff_mm_demuxer
Definition: mm.c:190
static AVPacket pkt
Format I/O context.
Definition: avformat.h:1342
static int read_header(AVFormatContext *s)
Definition: mm.c:85
#define MM_TYPE_AUDIO
Definition: mm.c:48
int width
Video only.
Definition: avcodec.h:3950
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4441
#define height
uint8_t * data
Definition: avcodec.h:1430
#define MM_TYPE_INTRA_HHV
Definition: mm.c:46
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition: utils.c:310
uint64_t channel_layout
Audio only.
Definition: avcodec.h:3986
#define av_log(a,...)
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:648
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:86
#define MM_HEADER_LEN_V
Definition: mm.c:51
#define MM_TYPE_INTER_HHV
Definition: mm.c:47
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:770
#define AVERROR(e)
Definition: error.h:43
unsigned int video_pts
Definition: mm.c:58
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
#define MM_HEADER_LEN_AV
Definition: mm.c:52
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3880
uint16_t width
Definition: gdv.c:47
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:451
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:450
#define MM_TYPE_INTRA_HH
Definition: mm.c:44
static int read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mm.c:138
audio channel layout utility functions
unsigned int audio_pts
Definition: mm.c:58
static int read_probe(AVProbeData *pd)
Definition: jvdec.c:55
uint8_t w
Definition: llviddspenc.c:38
#define AV_RL32
Definition: intreadwrite.h:146
Stream structure.
Definition: avformat.h:873
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
AVIOContext * pb
I/O context.
Definition: avformat.h:1384
#define MM_TYPE_INTRA
Definition: mm.c:43
cl_device_type type
#define MM_TYPE_HEADER
Definition: mm.c:41
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:458
This structure contains the data a format has to probe a file.
Definition: avformat.h:448
int sample_rate
Audio only.
Definition: avcodec.h:3994
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:754
Main libavformat public API header.
#define MM_TYPE_INTER
Definition: mm.c:42
#define MM_TYPE_PALETTE
Definition: mm.c:49
int len
#define MM_TYPE_INTER_HH
Definition: mm.c:45
void * priv_data
Format private data.
Definition: avformat.h:1370
int channels
Audio only.
Definition: avcodec.h:3990
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:647
static int probe(AVProbeData *p)
Definition: mm.c:61
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1020
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3888
const char int length
Definition: avisynth_c.h:768
int stream_index
Definition: avcodec.h:1432
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.
Definition: avcodec.h:1407
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1423