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