Libav
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 
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 {
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->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;
129  st->codec->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->size = length;
180  pkt->stream_index = 1;
181  pkt->pts = mm->audio_pts++;
182  return 0;
183 
184  default :
185  av_log(s, AV_LOG_INFO, "unknown chunk type 0x%x\n", type);
186  avio_skip(pb, length);
187  }
188  }
189 }
190 
192  .name = "mm",
193  .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM"),
194  .priv_data_size = sizeof(MmDemuxContext),
195  .read_probe = probe,
198 };
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: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:2821
int size
Definition: avcodec.h:974
#define AV_RL16
Definition: intreadwrite.h:42
AVInputFormat ff_mm_demuxer
Definition: mm.c:191
Format I/O context.
Definition: avformat.h:922
static int read_header(AVFormatContext *s)
Definition: mm.c:85
#define MM_TYPE_AUDIO
Definition: mm.c:48
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:2518
uint8_t * data
Definition: avcodec.h:973
#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:117
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:452
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:81
#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:564
#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:150
#define MM_HEADER_LEN_AV
Definition: mm.c:52
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:168
uint64_t channel_layout
Audio channel layout.
Definition: avcodec.h:1852
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:718
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:398
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:397
#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
int width
picture width / height.
Definition: avcodec.h:1224
static av_always_inline int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: avio.h:210
#define AV_RL32
Definition: intreadwrite.h:146
Stream structure.
Definition: avformat.h:699
NULL
Definition: eval.c:55
static int width
Definition: utils.c:156
#define AV_LOG_INFO
Standard information.
Definition: log.h:134
enum AVMediaType codec_type
Definition: avcodec.h:1058
enum AVCodecID codec_id
Definition: avcodec.h:1067
int sample_rate
samples per second
Definition: avcodec.h:1791
AVIOContext * pb
I/O context.
Definition: avformat.h:964
#define MM_TYPE_INTRA
Definition: mm.c:43
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
Definition: avcodec.h:1082
#define MM_TYPE_HEADER
Definition: mm.c:41
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:402
This structure contains the data a format has to probe a file.
Definition: avformat.h:395
int height
Definition: gxfenc.c:72
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:548
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
int channels
number of audio channels
Definition: avcodec.h:1792
void * priv_data
Format private data.
Definition: avformat.h:950
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:525
static int probe(AVProbeData *p)
Definition: mm.c:61
int stream_index
Definition: avcodec.h:975
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.
Definition: avcodec.h:950
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:966