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 Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
34 #include "libavutil/intreadwrite.h"
35 #include "avformat.h"
36 #include "internal.h"
37 
38 #define MM_PREAMBLE_SIZE 6
39 
40 #define MM_TYPE_HEADER 0x0
41 #define MM_TYPE_INTER 0x5
42 #define MM_TYPE_INTRA 0x8
43 #define MM_TYPE_INTRA_HH 0xc
44 #define MM_TYPE_INTER_HH 0xd
45 #define MM_TYPE_INTRA_HHV 0xe
46 #define MM_TYPE_INTER_HHV 0xf
47 #define MM_TYPE_AUDIO 0x15
48 #define MM_TYPE_PALETTE 0x31
49 
50 #define MM_HEADER_LEN_V 0x16 /* video only */
51 #define MM_HEADER_LEN_AV 0x18 /* video + audio */
52 
53 #define MM_PALETTE_COUNT 128
54 #define MM_PALETTE_SIZE (MM_PALETTE_COUNT*3)
55 
56 typedef struct {
57  unsigned int audio_pts, video_pts;
59 
60 static int probe(AVProbeData *p)
61 {
62  int len, type, fps, w, h;
64  return 0;
65  /* the first chunk is always the header */
66  if (AV_RL16(&p->buf[0]) != MM_TYPE_HEADER)
67  return 0;
68  len = AV_RL32(&p->buf[2]);
69  if (len != MM_HEADER_LEN_V && len != MM_HEADER_LEN_AV)
70  return 0;
71  fps = AV_RL16(&p->buf[8]);
72  w = AV_RL16(&p->buf[12]);
73  h = AV_RL16(&p->buf[14]);
74  if (!fps || fps > 60 || !w || w > 2048 || !h || h > 2048)
75  return 0;
76  type = AV_RL16(&p->buf[len]);
77  if (!type || type > 0x31)
78  return 0;
79 
80  /* only return half certainty since this check is a bit sketchy */
81  return AVPROBE_SCORE_MAX / 2;
82 }
83 
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->codec->codec_tag = 0; /* no fourcc */
115  st->codec->width = width;
116  st->codec->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->codec->codec_tag = 0; /* no fourcc */
127  st->codec->channels = 1;
128  st->codec->sample_rate = 8000;
129  avpriv_set_pts_info(st, 64, 1, 8000); /* 8000 hz */
130  }
131 
132  mm->audio_pts = 0;
133  mm->video_pts = 0;
134  return 0;
135 }
136 
138  AVPacket *pkt)
139 {
140  MmDemuxContext *mm = s->priv_data;
141  AVIOContext *pb = s->pb;
142  unsigned char preamble[MM_PREAMBLE_SIZE];
143  unsigned int type, length;
144 
145  while(1) {
146 
147  if (avio_read(pb, preamble, MM_PREAMBLE_SIZE) != MM_PREAMBLE_SIZE) {
148  return AVERROR(EIO);
149  }
150 
151  type = AV_RL16(&preamble[0]);
152  length = AV_RL16(&preamble[2]);
153 
154  switch(type) {
155  case MM_TYPE_PALETTE :
156  case MM_TYPE_INTER :
157  case MM_TYPE_INTRA :
158  case MM_TYPE_INTRA_HH :
159  case MM_TYPE_INTER_HH :
160  case MM_TYPE_INTRA_HHV :
161  case MM_TYPE_INTER_HHV :
162  /* output preamble + data */
163  if (av_new_packet(pkt, length + MM_PREAMBLE_SIZE))
164  return AVERROR(ENOMEM);
165  memcpy(pkt->data, preamble, MM_PREAMBLE_SIZE);
166  if (avio_read(pb, pkt->data + MM_PREAMBLE_SIZE, length) != length)
167  return AVERROR(EIO);
168  pkt->size = length + MM_PREAMBLE_SIZE;
169  pkt->stream_index = 0;
170  pkt->pts = mm->video_pts;
171  if (type!=MM_TYPE_PALETTE)
172  mm->video_pts++;
173  return 0;
174 
175  case MM_TYPE_AUDIO :
176  if (av_get_packet(s->pb, pkt, length)<0)
177  return AVERROR(ENOMEM);
178  pkt->size = length;
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 format"),
193  .priv_data_size = sizeof(MmDemuxContext),
194  .read_probe = probe,
197 };
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
#define MM_PREAMBLE_SIZE
Definition: mm.c:38
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the pts for a given stream.
Definition: utils.c:3828
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:60
int size
Definition: avcodec.h:909
int width
Definition: rotozoom.c:164
AVInputFormat ff_mm_demuxer
Definition: mm.c:190
Format I/O context.
Definition: avformat.h:863
#define MM_TYPE_AUDIO
Definition: mm.c:47
uint8_t * data
Definition: avcodec.h:908
#define MM_TYPE_INTRA_HHV
Definition: mm.c:45
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:269
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:652
#define MM_HEADER_LEN_V
Definition: mm.c:50
#define MM_TYPE_INTER_HHV
Definition: mm.c:46
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:738
#define AVERROR(e)
Definition: error.h:43
unsigned int video_pts
Definition: mm.c:57
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:191
#define MM_HEADER_LEN_AV
Definition: mm.c:51
AV_RL32
Definition: bytestream.h:89
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:140
AVStream * avformat_new_stream(AVFormatContext *s, AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:2776
AVCodecContext * codec
codec context
Definition: avformat.h:623
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:342
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:341
#define MM_TYPE_INTRA_HH
Definition: mm.c:43
static int read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mm.c:137
unsigned int audio_pts
Definition: mm.c:57
int width
picture width / height.
Definition: avcodec.h:1408
static av_always_inline int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: avio.h:483
static int read_probe(AVProbeData *p)
Definition: img2.c:185
Stream structure.
Definition: avformat.h:620
NULL
Definition: eval.c:50
enum AVMediaType codec_type
Definition: avcodec.h:1574
int sample_rate
samples per second
Definition: avcodec.h:1456
AVIOContext * pb
Definition: avformat.h:896
#define MM_TYPE_INTRA
Definition: mm.c:42
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
Definition: avcodec.h:1590
#define MM_TYPE_HEADER
Definition: mm.c:40
This structure contains the data a format has to probe a file.
Definition: avformat.h:339
int height
Definition: gxfenc.c:73
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:345
static int read_header(AVFormatContext *s, AVFormatParameters *ap)
Definition: mm.c:84
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:722
Main libavformat public API header.
AV_WL32 AV_WL24 AV_RL16
Definition: bytestream.h:89
#define MM_TYPE_INTER
Definition: mm.c:41
static AVRational frame_rate
Definition: ffmpeg.c:137
#define MM_TYPE_PALETTE
Definition: mm.c:48
int len
#define MM_TYPE_INTER_HH
Definition: mm.c:44
int channels
number of audio channels
Definition: avcodec.h:1457
void * priv_data
Format private data.
Definition: avformat.h:883
#define AV_LOG_INFO
Definition: log.h:119
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:460
static int probe(AVProbeData *p)
Definition: mm.c:60
int stream_index
Definition: avcodec.h:910
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:901
enum CodecID codec_id
Definition: avcodec.h:1575