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
(
avio_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 Fri Dec 5 2014 04:42:03 for FFmpeg by
1.8.2