FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
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
34
#include "
libavutil/channel_layout.h
"
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
;
59
}
MmDemuxContext
;
60
61
static
int
probe
(
AVProbeData
*p)
62
{
63
int
len
,
type
, fps, w, h;
64
if
(p->
buf_size
<
MM_HEADER_LEN_AV
+
MM_PREAMBLE_SIZE
)
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 */
82
return
AVPROBE_SCORE_EXTENSION
;
83
}
84
85
static
int
read_header
(
AVFormatContext
*
s
)
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);
112
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
113
st->
codec
->
codec_id
=
AV_CODEC_ID_MMVIDEO
;
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);
124
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
125
st->
codec
->
codec_tag
= 0;
/* no fourcc */
126
st->
codec
->
codec_id
=
AV_CODEC_ID_PCM_U8
;
127
st->
codec
->
channels
= 1;
128
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
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
138
static
int
read_packet
(
AVFormatContext
*
s
,
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
190
AVInputFormat
ff_mm_demuxer
= {
191
.
name
=
"mm"
,
192
.long_name =
NULL_IF_CONFIG_SMALL
(
"American Laser Games MM"
),
193
.priv_data_size =
sizeof
(
MmDemuxContext
),
194
.
read_probe
=
probe
,
195
.
read_header
=
read_header
,
196
.
read_packet
=
read_packet
,
197
};
Generated on Sun Mar 8 2015 02:35:10 for FFmpeg by
1.8.2