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
tmv.c
Go to the documentation of this file.
1
/*
2
* 8088flex TMV file demuxer
3
* Copyright (c) 2009 Daniel Verkamp <daniel at drv.nu>
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
* 8088flex TMV file demuxer
25
* @author Daniel Verkamp
26
* @see http://www.oldskool.org/pc/8088_Corruption
27
*/
28
29
#include "
libavutil/channel_layout.h
"
30
#include "
libavutil/intreadwrite.h
"
31
#include "
avformat.h
"
32
#include "
internal.h
"
33
34
enum
{
35
TMV_PADDING
= 0x01,
36
TMV_STEREO
= 0x02,
37
};
38
39
#define TMV_TAG MKTAG('T', 'M', 'A', 'V')
40
41
typedef
struct
TMVContext
{
42
unsigned
audio_chunk_size
;
43
unsigned
video_chunk_size
;
44
unsigned
padding
;
45
unsigned
stream_index
;
46
}
TMVContext
;
47
48
#define TMV_HEADER_SIZE 12
49
50
#define PROBE_MIN_SAMPLE_RATE 5000
51
#define PROBE_MAX_FPS 120
52
#define PROBE_MIN_AUDIO_SIZE (PROBE_MIN_SAMPLE_RATE / PROBE_MAX_FPS)
53
54
static
int
tmv_probe
(
AVProbeData
*p)
55
{
56
if
(
AV_RL32
(p->
buf
) ==
TMV_TAG
&&
57
AV_RL16
(p->
buf
+4) >=
PROBE_MIN_SAMPLE_RATE
&&
58
AV_RL16
(p->
buf
+6) >=
PROBE_MIN_AUDIO_SIZE
&&
59
!p->
buf
[8] &&
// compression method
60
p->
buf
[9] &&
// char cols
61
p->
buf
[10])
// char rows
62
return
AVPROBE_SCORE_MAX
/
63
((p->
buf
[9] == 40 && p->
buf
[10] == 25) ? 1 : 4);
64
return
0;
65
}
66
67
static
int
tmv_read_header
(
AVFormatContext
*
s
)
68
{
69
TMVContext
*tmv = s->
priv_data
;
70
AVIOContext
*pb = s->
pb
;
71
AVStream
*vst, *ast;
72
AVRational
fps;
73
unsigned
comp_method, char_cols, char_rows, features;
74
75
if
(
avio_rl32
(pb) !=
TMV_TAG
)
76
return
-1;
77
78
if
(!(vst =
avformat_new_stream
(s, NULL)))
79
return
AVERROR
(ENOMEM);
80
81
if
(!(ast =
avformat_new_stream
(s, NULL)))
82
return
AVERROR
(ENOMEM);
83
84
ast->
codec
->
sample_rate
=
avio_rl16
(pb);
85
if
(!ast->
codec
->
sample_rate
) {
86
av_log
(s,
AV_LOG_ERROR
,
"invalid sample rate\n"
);
87
return
-1;
88
}
89
90
tmv->
audio_chunk_size
=
avio_rl16
(pb);
91
if
(!tmv->
audio_chunk_size
) {
92
av_log
(s,
AV_LOG_ERROR
,
"invalid audio chunk size\n"
);
93
return
-1;
94
}
95
96
comp_method =
avio_r8
(pb);
97
if
(comp_method) {
98
av_log
(s,
AV_LOG_ERROR
,
"unsupported compression method %d\n"
,
99
comp_method);
100
return
-1;
101
}
102
103
char_cols =
avio_r8
(pb);
104
char_rows =
avio_r8
(pb);
105
tmv->
video_chunk_size
= char_cols * char_rows * 2;
106
107
features =
avio_r8
(pb);
108
if
(features & ~(
TMV_PADDING
|
TMV_STEREO
)) {
109
av_log
(s,
AV_LOG_ERROR
,
"unsupported features 0x%02x\n"
,
110
features & ~(
TMV_PADDING
|
TMV_STEREO
));
111
return
-1;
112
}
113
114
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
115
ast->
codec
->
codec_id
=
AV_CODEC_ID_PCM_U8
;
116
if
(features &
TMV_STEREO
) {
117
ast->
codec
->
channels
= 2;
118
ast->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
119
}
else
{
120
ast->
codec
->
channels
= 1;
121
ast->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
122
}
123
ast->
codec
->
bits_per_coded_sample
= 8;
124
ast->
codec
->
bit_rate
= ast->
codec
->
sample_rate
*
125
ast->
codec
->
bits_per_coded_sample
;
126
avpriv_set_pts_info
(ast, 32, 1, ast->
codec
->
sample_rate
);
127
128
fps.
num
= ast->
codec
->
sample_rate
* ast->
codec
->
channels
;
129
fps.
den
= tmv->
audio_chunk_size
;
130
av_reduce
(&fps.
num
, &fps.
den
, fps.
num
, fps.
den
, 0xFFFFFFFFLL);
131
132
vst->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
133
vst->
codec
->
codec_id
=
AV_CODEC_ID_TMV
;
134
vst->
codec
->
pix_fmt
=
AV_PIX_FMT_PAL8
;
135
vst->
codec
->
width
= char_cols * 8;
136
vst->
codec
->
height
= char_rows * 8;
137
avpriv_set_pts_info
(vst, 32, fps.
den
, fps.
num
);
138
139
if
(features &
TMV_PADDING
)
140
tmv->
padding
=
141
((tmv->
video_chunk_size
+ tmv->
audio_chunk_size
+ 511) & ~511) -
142
(tmv->
video_chunk_size
+ tmv->
audio_chunk_size
);
143
144
vst->
codec
->
bit_rate
= ((tmv->
video_chunk_size
+ tmv->
padding
) *
145
fps.
num
* 8) / fps.
den
;
146
147
return
0;
148
}
149
150
static
int
tmv_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
151
{
152
TMVContext
*tmv = s->
priv_data
;
153
AVIOContext
*pb = s->
pb
;
154
int
ret
, pkt_size = tmv->
stream_index
?
155
tmv->
audio_chunk_size
: tmv->
video_chunk_size
;
156
157
if
(
url_feof
(pb))
158
return
AVERROR_EOF
;
159
160
ret =
av_get_packet
(pb, pkt, pkt_size);
161
162
if
(tmv->
stream_index
)
163
avio_skip
(pb, tmv->
padding
);
164
165
pkt->
stream_index
= tmv->
stream_index
;
166
tmv->
stream_index
^= 1;
167
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
168
169
return
ret
;
170
}
171
172
static
int
tmv_read_seek
(
AVFormatContext
*
s
,
int
stream_index,
173
int64_t timestamp,
int
flags
)
174
{
175
TMVContext
*tmv = s->
priv_data
;
176
int64_t pos;
177
178
if
(stream_index)
179
return
-1;
180
181
pos = timestamp *
182
(tmv->
audio_chunk_size
+ tmv->
video_chunk_size
+ tmv->
padding
);
183
184
if
(
avio_seek
(s->
pb
, pos +
TMV_HEADER_SIZE
, SEEK_SET) < 0)
185
return
-1;
186
tmv->
stream_index
= 0;
187
return
0;
188
}
189
190
AVInputFormat
ff_tmv_demuxer
= {
191
.
name
=
"tmv"
,
192
.long_name =
NULL_IF_CONFIG_SMALL
(
"8088flex TMV"
),
193
.priv_data_size =
sizeof
(
TMVContext
),
194
.
read_probe
=
tmv_probe
,
195
.
read_header
=
tmv_read_header
,
196
.
read_packet
=
tmv_read_packet
,
197
.
read_seek
=
tmv_read_seek
,
198
.
flags
=
AVFMT_GENERIC_INDEX
,
199
};
Generated on Sun Mar 23 2014 23:50:03 for FFmpeg by
1.8.2