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
dxa.c
Go to the documentation of this file.
1
/*
2
* DXA demuxer
3
* Copyright (c) 2007 Konstantin Shishkov
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
#include "
libavutil/intreadwrite.h
"
23
#include "
avformat.h
"
24
#include "
internal.h
"
25
#include "
riff.h
"
26
27
#define DXA_EXTRA_SIZE 9
28
29
typedef
struct
{
30
int
frames
;
31
int
has_sound
;
32
int
bpc
;
33
uint32_t
bytes_left
;
34
int64_t
wavpos
, vidpos;
35
int
readvid
;
36
}
DXAContext
;
37
38
static
int
dxa_probe
(
AVProbeData
*p)
39
{
40
int
w, h;
41
if
(p->
buf_size
< 15)
42
return
0;
43
w =
AV_RB16
(p->
buf
+ 11);
44
h =
AV_RB16
(p->
buf
+ 13);
45
/* check file header */
46
if
(p->
buf
[0] ==
'D'
&& p->
buf
[1] ==
'E'
&&
47
p->
buf
[2] ==
'X'
&& p->
buf
[3] ==
'A'
&&
48
w && w <= 2048 && h && h <= 2048)
49
return
AVPROBE_SCORE_MAX
;
50
else
51
return
0;
52
}
53
54
static
int
dxa_read_header
(
AVFormatContext
*
s
)
55
{
56
AVIOContext
*pb = s->
pb
;
57
DXAContext
*
c
= s->
priv_data
;
58
AVStream
*st, *ast;
59
uint32_t
tag
;
60
int32_t
fps;
61
int
w, h;
62
int
num, den;
63
int
flags
;
64
int
ret
;
65
66
tag =
avio_rl32
(pb);
67
if
(tag !=
MKTAG
(
'D'
,
'E'
,
'X'
,
'A'
))
68
return
AVERROR_INVALIDDATA
;
69
flags =
avio_r8
(pb);
70
c->
frames
=
avio_rb16
(pb);
71
if
(!c->
frames
){
72
av_log
(s,
AV_LOG_ERROR
,
"File contains no frames ???\n"
);
73
return
AVERROR_INVALIDDATA
;
74
}
75
76
fps =
avio_rb32
(pb);
77
if
(fps > 0){
78
den = 1000;
79
num = fps;
80
}
else
if
(fps < 0){
81
den = 100000;
82
num = -fps;
83
}
else
{
84
den = 10;
85
num = 1;
86
}
87
w =
avio_rb16
(pb);
88
h =
avio_rb16
(pb);
89
c->
has_sound
= 0;
90
91
st =
avformat_new_stream
(s, NULL);
92
if
(!st)
93
return
AVERROR
(ENOMEM);
94
95
// Parse WAV data header
96
if
(
avio_rl32
(pb) ==
MKTAG
(
'W'
,
'A'
,
'V'
,
'E'
)){
97
uint32_t
size
, fsize;
98
c->
has_sound
= 1;
99
size =
avio_rb32
(pb);
100
c->
vidpos
=
avio_tell
(pb) +
size
;
101
avio_skip
(pb, 16);
102
fsize =
avio_rl32
(pb);
103
104
ast =
avformat_new_stream
(s, NULL);
105
if
(!ast)
106
return
AVERROR
(ENOMEM);
107
ret =
ff_get_wav_header
(pb, ast->
codec
, fsize);
108
if
(ret < 0)
109
return
ret
;
110
if
(ast->
codec
->
sample_rate
> 0)
111
avpriv_set_pts_info
(ast, 64, 1, ast->
codec
->
sample_rate
);
112
// find 'data' chunk
113
while
(
avio_tell
(pb) < c->
vidpos
&& !
url_feof
(pb)){
114
tag =
avio_rl32
(pb);
115
fsize =
avio_rl32
(pb);
116
if
(tag ==
MKTAG
(
'd'
,
'a'
,
't'
,
'a'
))
break
;
117
avio_skip
(pb, fsize);
118
}
119
c->
bpc
= (fsize + c->
frames
- 1) / c->
frames
;
120
if
(ast->
codec
->
block_align
)
121
c->
bpc
= ((c->
bpc
+ ast->
codec
->
block_align
- 1) / ast->
codec
->
block_align
) * ast->
codec
->
block_align
;
122
c->
bytes_left
= fsize;
123
c->
wavpos
=
avio_tell
(pb);
124
avio_seek
(pb, c->
vidpos
, SEEK_SET);
125
}
126
127
/* now we are ready: build format streams */
128
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
129
st->
codec
->
codec_id
=
AV_CODEC_ID_DXA
;
130
st->
codec
->
width
= w;
131
st->
codec
->
height
= h;
132
av_reduce
(&den, &num, den, num, (1UL<<31)-1);
133
avpriv_set_pts_info
(st, 33, num, den);
134
/* flags & 0x80 means that image is interlaced,
135
* flags & 0x40 means that image has double height
136
* either way set true height
137
*/
138
if
(flags & 0xC0){
139
st->
codec
->
height
>>= 1;
140
}
141
c->
readvid
= !c->
has_sound
;
142
c->
vidpos
=
avio_tell
(pb);
143
s->
start_time
= 0;
144
s->
duration
= (int64_t)c->
frames
*
AV_TIME_BASE
* num / den;
145
av_log
(s,
AV_LOG_DEBUG
,
"%d frame(s)\n"
,c->
frames
);
146
147
return
0;
148
}
149
150
static
int
dxa_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
151
{
152
DXAContext
*
c
= s->
priv_data
;
153
int
ret
;
154
uint32_t
size
;
155
uint8_t
buf
[
DXA_EXTRA_SIZE
], pal[768+4];
156
int
pal_size = 0;
157
158
if
(!c->
readvid
&& c->
has_sound
&& c->
bytes_left
){
159
c->
readvid
= 1;
160
avio_seek
(s->
pb
, c->
wavpos
, SEEK_SET);
161
size =
FFMIN
(c->
bytes_left
, c->
bpc
);
162
ret =
av_get_packet
(s->
pb
, pkt, size);
163
pkt->
stream_index
= 1;
164
if
(ret != size)
165
return
AVERROR
(EIO);
166
c->
bytes_left
-=
size
;
167
c->
wavpos
=
avio_tell
(s->
pb
);
168
return
0;
169
}
170
avio_seek
(s->
pb
, c->
vidpos
, SEEK_SET);
171
while
(!
url_feof
(s->
pb
) && c->
frames
){
172
if
((ret =
avio_read
(s->
pb
, buf, 4)) != 4) {
173
av_log
(s,
AV_LOG_ERROR
,
"failed reading chunk type\n"
);
174
return
ret < 0 ? ret :
AVERROR_INVALIDDATA
;
175
}
176
switch
(
AV_RL32
(buf)){
177
case
MKTAG
(
'N'
,
'U'
,
'L'
,
'L'
):
178
if
(
av_new_packet
(pkt, 4 + pal_size) < 0)
179
return
AVERROR
(ENOMEM);
180
pkt->
stream_index
= 0;
181
if
(pal_size) memcpy(pkt->
data
, pal, pal_size);
182
memcpy(pkt->
data
+ pal_size, buf, 4);
183
c->
frames
--;
184
c->
vidpos
=
avio_tell
(s->
pb
);
185
c->
readvid
= 0;
186
return
0;
187
case
MKTAG
(
'C'
,
'M'
,
'A'
,
'P'
):
188
pal_size = 768+4;
189
memcpy(pal, buf, 4);
190
avio_read
(s->
pb
, pal + 4, 768);
191
break
;
192
case
MKTAG
(
'F'
,
'R'
,
'A'
,
'M'
):
193
if
((ret =
avio_read
(s->
pb
, buf + 4,
DXA_EXTRA_SIZE
- 4)) !=
DXA_EXTRA_SIZE
- 4) {
194
av_log
(s,
AV_LOG_ERROR
,
"failed reading dxa_extra\n"
);
195
return
ret < 0 ? ret :
AVERROR_INVALIDDATA
;
196
}
197
size =
AV_RB32
(buf + 5);
198
if
(size > 0xFFFFFF){
199
av_log
(s,
AV_LOG_ERROR
,
"Frame size is too big: %d\n"
, size);
200
return
AVERROR_INVALIDDATA
;
201
}
202
if
(
av_new_packet
(pkt, size +
DXA_EXTRA_SIZE
+ pal_size) < 0)
203
return
AVERROR
(ENOMEM);
204
memcpy(pkt->
data
+ pal_size, buf,
DXA_EXTRA_SIZE
);
205
ret =
avio_read
(s->
pb
, pkt->
data
+
DXA_EXTRA_SIZE
+ pal_size, size);
206
if
(ret != size){
207
av_free_packet
(pkt);
208
return
AVERROR
(EIO);
209
}
210
if
(pal_size) memcpy(pkt->
data
, pal, pal_size);
211
pkt->
stream_index
= 0;
212
c->
frames
--;
213
c->
vidpos
=
avio_tell
(s->
pb
);
214
c->
readvid
= 0;
215
return
0;
216
default
:
217
av_log
(s,
AV_LOG_ERROR
,
"Unknown tag %c%c%c%c\n"
, buf[0], buf[1], buf[2], buf[3]);
218
return
AVERROR_INVALIDDATA
;
219
}
220
}
221
return
AVERROR_EOF
;
222
}
223
224
AVInputFormat
ff_dxa_demuxer
= {
225
.
name
=
"dxa"
,
226
.long_name =
NULL_IF_CONFIG_SMALL
(
"DXA"
),
227
.priv_data_size =
sizeof
(
DXAContext
),
228
.
read_probe
=
dxa_probe
,
229
.
read_header
=
dxa_read_header
,
230
.
read_packet
=
dxa_read_packet
,
231
};
Generated on Sun Mar 23 2014 23:49:53 for FFmpeg by
1.8.2