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