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
&& !
avio_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
(!
avio_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 Fri Dec 5 2014 04:41:53 for FFmpeg by
1.8.2