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
wc3movie.c
Go to the documentation of this file.
1
/*
2
* Wing Commander III Movie (.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
* Wing Commander III Movie file demuxer
25
* by Mike Melanson (melanson@pcisys.net)
26
* for more information on the WC3 .mve file format, visit:
27
* http://www.pcisys.net/~melanson/codecs/
28
*/
29
30
#include "
libavutil/channel_layout.h
"
31
#include "
libavutil/intreadwrite.h
"
32
#include "
libavutil/dict.h
"
33
#include "
avformat.h
"
34
#include "
internal.h
"
35
36
#define FORM_TAG MKTAG('F', 'O', 'R', 'M')
37
#define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
38
#define PC__TAG MKTAG('_', 'P', 'C', '_')
39
#define SOND_TAG MKTAG('S', 'O', 'N', 'D')
40
#define BNAM_TAG MKTAG('B', 'N', 'A', 'M')
41
#define SIZE_TAG MKTAG('S', 'I', 'Z', 'E')
42
#define PALT_TAG MKTAG('P', 'A', 'L', 'T')
43
#define INDX_TAG MKTAG('I', 'N', 'D', 'X')
44
#define BRCH_TAG MKTAG('B', 'R', 'C', 'H')
45
#define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
46
#define VGA__TAG MKTAG('V', 'G', 'A', ' ')
47
#define TEXT_TAG MKTAG('T', 'E', 'X', 'T')
48
#define AUDI_TAG MKTAG('A', 'U', 'D', 'I')
49
50
/* video resolution unless otherwise specified */
51
#define WC3_DEFAULT_WIDTH 320
52
#define WC3_DEFAULT_HEIGHT 165
53
54
/* always use the same PCM audio parameters */
55
#define WC3_SAMPLE_RATE 22050
56
#define WC3_AUDIO_CHANNELS 1
57
#define WC3_AUDIO_BITS 16
58
59
/* nice, constant framerate */
60
#define WC3_FRAME_FPS 15
61
62
#define PALETTE_SIZE (256 * 3)
63
64
typedef
struct
Wc3DemuxContext
{
65
int
width
;
66
int
height
;
67
int64_t
pts
;
68
int
video_stream_index
;
69
int
audio_stream_index
;
70
71
AVPacket
vpkt
;
72
73
}
Wc3DemuxContext
;
74
75
static
int
wc3_probe
(
AVProbeData
*p)
76
{
77
if
(p->
buf_size
< 12)
78
return
0;
79
80
if
((
AV_RL32
(&p->
buf
[0]) !=
FORM_TAG
) ||
81
(
AV_RL32
(&p->
buf
[8]) !=
MOVE_TAG
))
82
return
0;
83
84
return
AVPROBE_SCORE_MAX
;
85
}
86
87
static
int
wc3_read_header
(
AVFormatContext
*
s
)
88
{
89
Wc3DemuxContext
*wc3 = s->
priv_data
;
90
AVIOContext
*pb = s->
pb
;
91
unsigned
int
fourcc_tag;
92
unsigned
int
size
;
93
AVStream
*st;
94
int
ret
= 0;
95
char
*
buffer
;
96
97
/* default context members */
98
wc3->
width
=
WC3_DEFAULT_WIDTH
;
99
wc3->
height
=
WC3_DEFAULT_HEIGHT
;
100
wc3->
pts
= 0;
101
wc3->
video_stream_index
= wc3->
audio_stream_index
= 0;
102
av_init_packet
(&wc3->
vpkt
);
103
wc3->
vpkt
.
data
= NULL; wc3->
vpkt
.
size
= 0;
104
105
/* skip the first 3 32-bit numbers */
106
avio_skip
(pb, 12);
107
108
/* traverse through the chunks and load the header information before
109
* the first BRCH tag */
110
fourcc_tag =
avio_rl32
(pb);
111
size = (
avio_rb32
(pb) + 1) & (~1);
112
113
do
{
114
switch
(fourcc_tag) {
115
116
case
SOND_TAG
:
117
case
INDX_TAG
:
118
/* SOND unknown, INDX unnecessary; ignore both */
119
avio_skip
(pb, size);
120
break
;
121
122
case
PC__TAG
:
123
/* number of palettes, unneeded */
124
avio_skip
(pb, 12);
125
break
;
126
127
case
BNAM_TAG
:
128
/* load up the name */
129
buffer =
av_malloc
(size+1);
130
if
(!buffer)
131
return
AVERROR
(ENOMEM);
132
if
((ret =
avio_read
(pb, buffer, size)) != size)
133
return
AVERROR
(EIO);
134
buffer[
size
] = 0;
135
av_dict_set
(&s->
metadata
,
"title"
, buffer,
136
AV_DICT_DONT_STRDUP_VAL
);
137
break
;
138
139
case
SIZE_TAG
:
140
/* video resolution override */
141
wc3->
width
=
avio_rl32
(pb);
142
wc3->
height
=
avio_rl32
(pb);
143
break
;
144
145
case
PALT_TAG
:
146
/* one of several palettes */
147
avio_seek
(pb, -8, SEEK_CUR);
148
av_append_packet
(pb, &wc3->
vpkt
, 8 +
PALETTE_SIZE
);
149
break
;
150
151
default
:
152
av_log
(s,
AV_LOG_ERROR
,
" unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n"
,
153
(
uint8_t
)fourcc_tag, (
uint8_t
)(fourcc_tag >> 8), (
uint8_t
)(fourcc_tag >> 16), (
uint8_t
)(fourcc_tag >> 24),
154
(
uint8_t
)fourcc_tag, (
uint8_t
)(fourcc_tag >> 8), (
uint8_t
)(fourcc_tag >> 16), (
uint8_t
)(fourcc_tag >> 24));
155
return
AVERROR_INVALIDDATA
;
156
}
157
158
fourcc_tag =
avio_rl32
(pb);
159
/* chunk sizes are 16-bit aligned */
160
size = (
avio_rb32
(pb) + 1) & (~1);
161
if
(
url_feof
(pb))
162
return
AVERROR
(EIO);
163
164
}
while
(fourcc_tag !=
BRCH_TAG
);
165
166
/* initialize the decoder streams */
167
st =
avformat_new_stream
(s, NULL);
168
if
(!st)
169
return
AVERROR
(ENOMEM);
170
avpriv_set_pts_info
(st, 33, 1,
WC3_FRAME_FPS
);
171
wc3->
video_stream_index
= st->
index
;
172
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
173
st->
codec
->
codec_id
=
AV_CODEC_ID_XAN_WC3
;
174
st->
codec
->
codec_tag
= 0;
/* no fourcc */
175
st->
codec
->
width
= wc3->
width
;
176
st->
codec
->
height
= wc3->
height
;
177
178
st =
avformat_new_stream
(s, NULL);
179
if
(!st)
180
return
AVERROR
(ENOMEM);
181
avpriv_set_pts_info
(st, 33, 1,
WC3_FRAME_FPS
);
182
wc3->
audio_stream_index
= st->
index
;
183
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
184
st->
codec
->
codec_id
=
AV_CODEC_ID_PCM_S16LE
;
185
st->
codec
->
codec_tag
= 1;
186
st->
codec
->
channels
=
WC3_AUDIO_CHANNELS
;
187
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
188
st->
codec
->
bits_per_coded_sample
=
WC3_AUDIO_BITS
;
189
st->
codec
->
sample_rate
=
WC3_SAMPLE_RATE
;
190
st->
codec
->
bit_rate
= st->
codec
->
channels
* st->
codec
->
sample_rate
*
191
st->
codec
->
bits_per_coded_sample
;
192
st->
codec
->
block_align
=
WC3_AUDIO_BITS
*
WC3_AUDIO_CHANNELS
;
193
194
return
0;
195
}
196
197
static
int
wc3_read_packet
(
AVFormatContext
*
s
,
198
AVPacket
*
pkt
)
199
{
200
Wc3DemuxContext
*wc3 = s->
priv_data
;
201
AVIOContext
*pb = s->
pb
;
202
unsigned
int
fourcc_tag;
203
unsigned
int
size
;
204
int
packet_read = 0;
205
int
ret
= 0;
206
unsigned
char
text[1024];
207
208
while
(!packet_read) {
209
210
fourcc_tag =
avio_rl32
(pb);
211
/* chunk sizes are 16-bit aligned */
212
size = (
avio_rb32
(pb) + 1) & (~1);
213
if
(
url_feof
(pb))
214
return
AVERROR
(EIO);
215
216
switch
(fourcc_tag) {
217
218
case
BRCH_TAG
:
219
/* no-op */
220
break
;
221
222
case
SHOT_TAG
:
223
/* load up new palette */
224
avio_seek
(pb, -8, SEEK_CUR);
225
av_append_packet
(pb, &wc3->
vpkt
, 8 + 4);
226
break
;
227
228
case
VGA__TAG
:
229
/* send out video chunk */
230
avio_seek
(pb, -8, SEEK_CUR);
231
ret=
av_append_packet
(pb, &wc3->
vpkt
, 8 + size);
232
// ignore error if we have some data
233
if
(wc3->
vpkt
.
size
> 0)
234
ret = 0;
235
*pkt = wc3->
vpkt
;
236
wc3->
vpkt
.
data
= NULL; wc3->
vpkt
.
size
= 0;
237
pkt->
stream_index
= wc3->
video_stream_index
;
238
pkt->
pts
= wc3->
pts
;
239
packet_read = 1;
240
break
;
241
242
case
TEXT_TAG
:
243
/* subtitle chunk */
244
#if 0
245
avio_skip
(pb, size);
246
#else
247
if
((
unsigned
)size >
sizeof
(text) || (ret =
avio_read
(pb, text, size)) != size)
248
ret =
AVERROR
(EIO);
249
else
{
250
int
i = 0;
251
av_log
(s,
AV_LOG_DEBUG
,
"Subtitle time!\n"
);
252
av_log
(s,
AV_LOG_DEBUG
,
" inglish: %s\n"
, &text[i + 1]);
253
i += text[i] + 1;
254
av_log
(s,
AV_LOG_DEBUG
,
" doytsch: %s\n"
, &text[i + 1]);
255
i += text[i] + 1;
256
av_log
(s,
AV_LOG_DEBUG
,
" fronsay: %s\n"
, &text[i + 1]);
257
}
258
#endif
259
break
;
260
261
case
AUDI_TAG
:
262
/* send out audio chunk */
263
ret=
av_get_packet
(pb, pkt, size);
264
pkt->
stream_index
= wc3->
audio_stream_index
;
265
pkt->
pts
= wc3->
pts
;
266
267
/* time to advance pts */
268
wc3->
pts
++;
269
270
packet_read = 1;
271
break
;
272
273
default
:
274
av_log
(s,
AV_LOG_ERROR
,
" unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n"
,
275
(
uint8_t
)fourcc_tag, (
uint8_t
)(fourcc_tag >> 8), (
uint8_t
)(fourcc_tag >> 16), (
uint8_t
)(fourcc_tag >> 24),
276
(
uint8_t
)fourcc_tag, (
uint8_t
)(fourcc_tag >> 8), (
uint8_t
)(fourcc_tag >> 16), (
uint8_t
)(fourcc_tag >> 24));
277
ret =
AVERROR_INVALIDDATA
;
278
packet_read = 1;
279
break
;
280
}
281
}
282
283
return
ret
;
284
}
285
286
static
int
wc3_read_close
(
AVFormatContext
*
s
)
287
{
288
Wc3DemuxContext
*wc3 = s->
priv_data
;
289
290
if
(wc3->
vpkt
.
size
> 0)
291
av_free_packet
(&wc3->
vpkt
);
292
293
return
0;
294
}
295
296
AVInputFormat
ff_wc3_demuxer
= {
297
.
name
=
"wc3movie"
,
298
.long_name =
NULL_IF_CONFIG_SMALL
(
"Wing Commander III movie"
),
299
.priv_data_size =
sizeof
(
Wc3DemuxContext
),
300
.
read_probe
=
wc3_probe
,
301
.
read_header
=
wc3_read_header
,
302
.
read_packet
=
wc3_read_packet
,
303
.
read_close
=
wc3_read_close
,
304
};
Generated on Wed Jul 10 2013 23:48:15 for FFmpeg by
1.8.2