Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
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 Libav.
6
*
7
* Libav 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
* Libav 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 Libav; 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,
AVFormatParameters
*ap)
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
-1;
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
-1;
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
-1;
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
-1;
107
ret =
ff_get_wav_header
(pb, ast->
codec
, fsize);
108
if
(ret < 0)
109
return
ret;
110
// find 'data' chunk
111
while
(
avio_tell
(pb) < c->
vidpos
&& !pb->
eof_reached
){
112
tag =
avio_rl32
(pb);
113
fsize =
avio_rl32
(pb);
114
if
(tag ==
MKTAG
(
'd'
,
'a'
,
't'
,
'a'
))
break
;
115
avio_skip
(pb, fsize);
116
}
117
c->
bpc
= (fsize + c->
frames
- 1) / c->
frames
;
118
if
(ast->
codec
->
block_align
)
119
c->
bpc
= ((c->
bpc
+ ast->
codec
->
block_align
- 1) / ast->
codec
->
block_align
) * ast->
codec
->
block_align
;
120
c->
bytes_left
= fsize;
121
c->
wavpos
=
avio_tell
(pb);
122
avio_seek
(pb, c->
vidpos
, SEEK_SET);
123
}
124
125
/* now we are ready: build format streams */
126
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
127
st->
codec
->
codec_id
=
CODEC_ID_DXA
;
128
st->
codec
->
width
= w;
129
st->
codec
->
height
= h;
130
av_reduce
(&den, &num, den, num, (1UL<<31)-1);
131
avpriv_set_pts_info
(st, 33, num, den);
132
/* flags & 0x80 means that image is interlaced,
133
* flags & 0x40 means that image has double height
134
* either way set true height
135
*/
136
if
(flags & 0xC0){
137
st->
codec
->
height
>>= 1;
138
}
139
c->
readvid
= !c->
has_sound
;
140
c->
vidpos
=
avio_tell
(pb);
141
s->
start_time
= 0;
142
s->
duration
= (int64_t)c->
frames
*
AV_TIME_BASE
* num / den;
143
av_log
(s,
AV_LOG_DEBUG
,
"%d frame(s)\n"
,c->
frames
);
144
145
return
0;
146
}
147
148
static
int
dxa_read_packet
(
AVFormatContext
*s,
AVPacket
*pkt)
149
{
150
DXAContext
*c = s->
priv_data
;
151
int
ret;
152
uint32_t
size
;
153
uint8_t buf[
DXA_EXTRA_SIZE
], pal[768+4];
154
int
pal_size = 0;
155
156
if
(!c->
readvid
&& c->
has_sound
&& c->
bytes_left
){
157
c->
readvid
= 1;
158
avio_seek
(s->
pb
, c->
wavpos
, SEEK_SET);
159
size =
FFMIN
(c->
bytes_left
, c->
bpc
);
160
ret =
av_get_packet
(s->
pb
, pkt, size);
161
pkt->
stream_index
= 1;
162
if
(ret != size)
163
return
AVERROR
(EIO);
164
c->
bytes_left
-=
size
;
165
c->
wavpos
=
avio_tell
(s->
pb
);
166
return
0;
167
}
168
avio_seek
(s->
pb
, c->
vidpos
, SEEK_SET);
169
while
(!s->
pb
->
eof_reached
&& c->
frames
){
170
avio_read
(s->
pb
, buf, 4);
171
switch
(
AV_RL32
(buf)){
172
case
MKTAG
(
'N'
,
'U'
,
'L'
,
'L'
):
173
if
(
av_new_packet
(pkt, 4 + pal_size) < 0)
174
return
AVERROR
(ENOMEM);
175
pkt->
stream_index
= 0;
176
if
(pal_size) memcpy(pkt->
data
, pal, pal_size);
177
memcpy(pkt->
data
+ pal_size, buf, 4);
178
c->
frames
--;
179
c->
vidpos
=
avio_tell
(s->
pb
);
180
c->
readvid
= 0;
181
return
0;
182
case
MKTAG
(
'C'
,
'M'
,
'A'
,
'P'
):
183
pal_size = 768+4;
184
memcpy(pal, buf, 4);
185
avio_read
(s->
pb
, pal + 4, 768);
186
break
;
187
case
MKTAG
(
'F'
,
'R'
,
'A'
,
'M'
):
188
avio_read
(s->
pb
, buf + 4,
DXA_EXTRA_SIZE
- 4);
189
size =
AV_RB32
(buf + 5);
190
if
(size > 0xFFFFFF){
191
av_log
(s,
AV_LOG_ERROR
,
"Frame size is too big: %d\n"
, size);
192
return
-1;
193
}
194
if
(
av_new_packet
(pkt, size +
DXA_EXTRA_SIZE
+ pal_size) < 0)
195
return
AVERROR
(ENOMEM);
196
memcpy(pkt->
data
+ pal_size, buf,
DXA_EXTRA_SIZE
);
197
ret =
avio_read
(s->
pb
, pkt->
data
+
DXA_EXTRA_SIZE
+ pal_size, size);
198
if
(ret != size){
199
av_free_packet
(pkt);
200
return
AVERROR
(EIO);
201
}
202
if
(pal_size) memcpy(pkt->
data
, pal, pal_size);
203
pkt->
stream_index
= 0;
204
c->
frames
--;
205
c->
vidpos
=
avio_tell
(s->
pb
);
206
c->
readvid
= 0;
207
return
0;
208
default
:
209
av_log
(s,
AV_LOG_ERROR
,
"Unknown tag %c%c%c%c\n"
, buf[0], buf[1], buf[2], buf[3]);
210
return
-1;
211
}
212
}
213
return
AVERROR
(EIO);
214
}
215
216
AVInputFormat
ff_dxa_demuxer
= {
217
.
name
=
"dxa"
,
218
.long_name =
NULL_IF_CONFIG_SMALL
(
"DXA"
),
219
.priv_data_size =
sizeof
(
DXAContext
),
220
.
read_probe
=
dxa_probe
,
221
.
read_header
=
dxa_read_header
,
222
.
read_packet
=
dxa_read_packet
,
223
};