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
r3d.c
Go to the documentation of this file.
1
/*
2
* R3D REDCODE demuxer
3
* Copyright (c) 2008 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
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 "
libavutil/dict.h
"
24
#include "
libavutil/mathematics.h
"
25
#include "
avformat.h
"
26
#include "
internal.h
"
27
28
typedef
struct
{
29
unsigned
video_offsets_count
;
30
unsigned
*
video_offsets
;
31
unsigned
rdvo_offset
;
32
}
R3DContext
;
33
34
typedef
struct
{
35
unsigned
size
;
36
uint32_t
tag
;
37
uint64_t
offset
;
38
}
Atom
;
39
40
static
int
read_atom
(
AVFormatContext
*
s
,
Atom
*atom)
41
{
42
atom->
offset
=
avio_tell
(s->
pb
);
43
atom->
size
=
avio_rb32
(s->
pb
);
44
if
(atom->
size
< 8)
45
return
-1;
46
atom->
tag
=
avio_rl32
(s->
pb
);
47
av_dlog
(s,
"atom %u %.4s offset %#"
PRIx64
"\n"
,
48
atom->
size
, (
char
*)&atom->
tag
, atom->
offset
);
49
return
atom->
size
;
50
}
51
52
static
int
r3d_read_red1
(
AVFormatContext
*
s
)
53
{
54
AVStream
*st =
avformat_new_stream
(s, NULL);
55
char
filename[258];
56
int
tmp;
57
int
av_unused
tmp2;
58
AVRational
framerate;
59
60
if
(!st)
61
return
AVERROR
(ENOMEM);
62
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
63
st->
codec
->
codec_id
=
AV_CODEC_ID_JPEG2000
;
64
65
tmp =
avio_r8
(s->
pb
);
// major version
66
tmp2 =
avio_r8
(s->
pb
);
// minor version
67
av_dlog
(s,
"version %d.%d\n"
, tmp, tmp2);
68
69
tmp =
avio_rb16
(s->
pb
);
// unknown
70
av_dlog
(s,
"unknown1 %d\n"
, tmp);
71
72
tmp =
avio_rb32
(s->
pb
);
73
avpriv_set_pts_info
(st, 32, 1, tmp);
74
75
tmp =
avio_rb32
(s->
pb
);
// filenum
76
av_dlog
(s,
"filenum %d\n"
, tmp);
77
78
avio_skip
(s->
pb
, 32);
// unknown
79
80
st->
codec
->
width
=
avio_rb32
(s->
pb
);
81
st->
codec
->
height
=
avio_rb32
(s->
pb
);
82
83
tmp =
avio_rb16
(s->
pb
);
// unknown
84
av_dlog
(s,
"unknown2 %d\n"
, tmp);
85
86
framerate.
num
=
avio_rb16
(s->
pb
);
87
framerate.
den
=
avio_rb16
(s->
pb
);
88
if
(framerate.
num
> 0 && framerate.
den
> 0) {
89
#if FF_API_R_FRAME_RATE
90
st->
r_frame_rate
=
91
#endif
92
st->
avg_frame_rate
= framerate;
93
}
94
95
tmp =
avio_r8
(s->
pb
);
// audio channels
96
av_dlog
(s,
"audio channels %d\n"
, tmp);
97
if
(tmp > 0) {
98
AVStream
*ast =
avformat_new_stream
(s, NULL);
99
if
(!ast)
100
return
AVERROR
(ENOMEM);
101
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
102
ast->
codec
->
codec_id
=
AV_CODEC_ID_PCM_S32BE
;
103
ast->
codec
->
channels
= tmp;
104
avpriv_set_pts_info
(ast, 32, 1, st->
time_base
.
den
);
105
}
106
107
avio_read
(s->
pb
, filename, 257);
108
filename[
sizeof
(filename)-1] = 0;
109
av_dict_set
(&st->
metadata
,
"filename"
, filename, 0);
110
111
av_dlog
(s,
"filename %s\n"
, filename);
112
av_dlog
(s,
"resolution %dx%d\n"
, st->
codec
->
width
, st->
codec
->
height
);
113
av_dlog
(s,
"timescale %d\n"
, st->
time_base
.
den
);
114
av_dlog
(s,
"frame rate %d/%d\n"
,
115
framerate.
num
, framerate.
den
);
116
117
return
0;
118
}
119
120
static
int
r3d_read_rdvo
(
AVFormatContext
*
s
,
Atom
*atom)
121
{
122
R3DContext
*r3d = s->
priv_data
;
123
AVStream
*st = s->
streams
[0];
124
int
i;
125
126
r3d->
video_offsets_count
= (atom->
size
- 8) / 4;
127
r3d->
video_offsets
=
av_malloc
(atom->
size
);
128
if
(!r3d->
video_offsets
)
129
return
AVERROR
(ENOMEM);
130
131
for
(i = 0; i < r3d->
video_offsets_count
; i++) {
132
r3d->
video_offsets
[i] =
avio_rb32
(s->
pb
);
133
if
(!r3d->
video_offsets
[i]) {
134
r3d->
video_offsets_count
= i;
135
break
;
136
}
137
av_dlog
(s,
"video offset %d: %#x\n"
, i, r3d->
video_offsets
[i]);
138
}
139
140
if
(st->
avg_frame_rate
.
num
)
141
st->
duration
=
av_rescale_q
(r3d->
video_offsets_count
,
142
av_inv_q
(st->
avg_frame_rate
),
143
st->
time_base
);
144
av_dlog
(s,
"duration %"
PRId64
"\n"
, st->
duration
);
145
146
return
0;
147
}
148
149
static
void
r3d_read_reos
(
AVFormatContext
*
s
)
150
{
151
R3DContext
*r3d = s->
priv_data
;
152
int
av_unused
tmp;
153
154
r3d->
rdvo_offset
=
avio_rb32
(s->
pb
);
155
avio_rb32
(s->
pb
);
// rdvs offset
156
avio_rb32
(s->
pb
);
// rdao offset
157
avio_rb32
(s->
pb
);
// rdas offset
158
159
tmp =
avio_rb32
(s->
pb
);
160
av_dlog
(s,
"num video chunks %d\n"
, tmp);
161
162
tmp =
avio_rb32
(s->
pb
);
163
av_dlog
(s,
"num audio chunks %d\n"
, tmp);
164
165
avio_skip
(s->
pb
, 6*4);
166
}
167
168
static
int
r3d_read_header
(
AVFormatContext
*
s
)
169
{
170
R3DContext
*r3d = s->
priv_data
;
171
Atom
atom;
172
int
ret
;
173
174
if
(
read_atom
(s, &atom) < 0) {
175
av_log
(s,
AV_LOG_ERROR
,
"error reading atom\n"
);
176
return
-1;
177
}
178
if
(atom.
tag
==
MKTAG
(
'R'
,
'E'
,
'D'
,
'1'
)) {
179
if
((ret =
r3d_read_red1
(s)) < 0) {
180
av_log
(s,
AV_LOG_ERROR
,
"error parsing 'red1' atom\n"
);
181
return
ret
;
182
}
183
}
else
{
184
av_log
(s,
AV_LOG_ERROR
,
"could not find 'red1' atom\n"
);
185
return
-1;
186
}
187
188
s->
data_offset
=
avio_tell
(s->
pb
);
189
av_dlog
(s,
"data offset %#"
PRIx64
"\n"
, s->
data_offset
);
190
if
(!s->
pb
->
seekable
)
191
return
0;
192
// find REOB/REOF/REOS to load index
193
avio_seek
(s->
pb
,
avio_size
(s->
pb
)-48-8, SEEK_SET);
194
if
(
read_atom
(s, &atom) < 0)
195
av_log
(s,
AV_LOG_ERROR
,
"error reading end atom\n"
);
196
197
if
(atom.
tag
!=
MKTAG
(
'R'
,
'E'
,
'O'
,
'B'
) &&
198
atom.
tag
!=
MKTAG
(
'R'
,
'E'
,
'O'
,
'F'
) &&
199
atom.
tag
!=
MKTAG
(
'R'
,
'E'
,
'O'
,
'S'
))
200
goto
out
;
201
202
r3d_read_reos
(s);
203
204
if
(r3d->
rdvo_offset
) {
205
avio_seek
(s->
pb
, r3d->
rdvo_offset
, SEEK_SET);
206
if
(
read_atom
(s, &atom) < 0)
207
av_log
(s,
AV_LOG_ERROR
,
"error reading 'rdvo' atom\n"
);
208
if
(atom.
tag
==
MKTAG
(
'R'
,
'D'
,
'V'
,
'O'
)) {
209
if
(
r3d_read_rdvo
(s, &atom) < 0)
210
av_log
(s,
AV_LOG_ERROR
,
"error parsing 'rdvo' atom\n"
);
211
}
212
}
213
214
out
:
215
avio_seek
(s->
pb
, s->
data_offset
, SEEK_SET);
216
return
0;
217
}
218
219
static
int
r3d_read_redv
(
AVFormatContext
*
s
,
AVPacket
*
pkt
,
Atom
*atom)
220
{
221
AVStream
*st = s->
streams
[0];
222
int
tmp;
223
int
av_unused
tmp2;
224
uint64_t pos =
avio_tell
(s->
pb
);
225
unsigned
dts;
226
int
ret
;
227
228
dts =
avio_rb32
(s->
pb
);
229
230
tmp =
avio_rb32
(s->
pb
);
231
av_dlog
(s,
"frame num %d\n"
, tmp);
232
233
tmp =
avio_r8
(s->
pb
);
// major version
234
tmp2 =
avio_r8
(s->
pb
);
// minor version
235
av_dlog
(s,
"version %d.%d\n"
, tmp, tmp2);
236
237
tmp =
avio_rb16
(s->
pb
);
// unknown
238
av_dlog
(s,
"unknown %d\n"
, tmp);
239
240
if
(tmp > 4) {
241
tmp =
avio_rb16
(s->
pb
);
// unknown
242
av_dlog
(s,
"unknown %d\n"
, tmp);
243
244
tmp =
avio_rb16
(s->
pb
);
// unknown
245
av_dlog
(s,
"unknown %d\n"
, tmp);
246
247
tmp =
avio_rb32
(s->
pb
);
248
av_dlog
(s,
"width %d\n"
, tmp);
249
tmp =
avio_rb32
(s->
pb
);
250
av_dlog
(s,
"height %d\n"
, tmp);
251
252
tmp =
avio_rb32
(s->
pb
);
253
av_dlog
(s,
"metadata len %d\n"
, tmp);
254
}
255
tmp = atom->
size
- 8 - (
avio_tell
(s->
pb
) - pos);
256
if
(tmp < 0)
257
return
-1;
258
ret =
av_get_packet
(s->
pb
, pkt, tmp);
259
if
(ret < 0) {
260
av_log
(s,
AV_LOG_ERROR
,
"error reading video packet\n"
);
261
return
-1;
262
}
263
264
pkt->
stream_index
= 0;
265
pkt->
dts
= dts;
266
if
(st->
avg_frame_rate
.
num
)
267
pkt->
duration
= (uint64_t)st->
time_base
.
den
*
268
st->
avg_frame_rate
.
den
/st->
avg_frame_rate
.
num
;
269
av_dlog
(s,
"pkt dts %"
PRId64
" duration %d\n"
, pkt->
dts
, pkt->
duration
);
270
271
return
0;
272
}
273
274
static
int
r3d_read_reda
(
AVFormatContext
*
s
,
AVPacket
*
pkt
,
Atom
*atom)
275
{
276
AVStream
*st = s->
streams
[1];
277
int
av_unused
tmp, tmp2;
278
int
samples,
size
;
279
uint64_t pos =
avio_tell
(s->
pb
);
280
unsigned
dts;
281
int
ret
;
282
283
dts =
avio_rb32
(s->
pb
);
284
285
st->
codec
->
sample_rate
=
avio_rb32
(s->
pb
);
286
if
(st->
codec
->
sample_rate
<= 0) {
287
av_log
(s,
AV_LOG_ERROR
,
"Bad sample rate\n"
);
288
return
AVERROR_INVALIDDATA
;
289
}
290
291
samples =
avio_rb32
(s->
pb
);
292
293
tmp =
avio_rb32
(s->
pb
);
294
av_dlog
(s,
"packet num %d\n"
, tmp);
295
296
tmp =
avio_rb16
(s->
pb
);
// unknown
297
av_dlog
(s,
"unknown %d\n"
, tmp);
298
299
tmp =
avio_r8
(s->
pb
);
// major version
300
tmp2 =
avio_r8
(s->
pb
);
// minor version
301
av_dlog
(s,
"version %d.%d\n"
, tmp, tmp2);
302
303
tmp =
avio_rb32
(s->
pb
);
// unknown
304
av_dlog
(s,
"unknown %d\n"
, tmp);
305
306
size = atom->
size
- 8 - (
avio_tell
(s->
pb
) - pos);
307
if
(size < 0)
308
return
-1;
309
ret =
av_get_packet
(s->
pb
, pkt, size);
310
if
(ret < 0) {
311
av_log
(s,
AV_LOG_ERROR
,
"error reading audio packet\n"
);
312
return
ret
;
313
}
314
315
pkt->
stream_index
= 1;
316
pkt->
dts
= dts;
317
if
(st->
codec
->
sample_rate
)
318
pkt->
duration
=
av_rescale
(samples, st->
time_base
.
den
, st->
codec
->
sample_rate
);
319
av_dlog
(s,
"pkt dts %"
PRId64
" duration %d samples %d sample rate %d\n"
,
320
pkt->
dts
, pkt->
duration
, samples, st->
codec
->
sample_rate
);
321
322
return
0;
323
}
324
325
static
int
r3d_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
326
{
327
Atom
atom;
328
int
err = 0;
329
330
while
(!err) {
331
if
(
read_atom
(s, &atom) < 0) {
332
err = -1;
333
break
;
334
}
335
switch
(atom.
tag
) {
336
case
MKTAG
(
'R'
,
'E'
,
'D'
,
'V'
):
337
if
(s->
streams
[0]->
discard
==
AVDISCARD_ALL
)
338
goto
skip;
339
if
(!(err =
r3d_read_redv
(s, pkt, &atom)))
340
return
0;
341
break
;
342
case
MKTAG
(
'R'
,
'E'
,
'D'
,
'A'
):
343
if
(s->
nb_streams
< 2)
344
return
-1;
345
if
(s->
streams
[1]->
discard
==
AVDISCARD_ALL
)
346
goto
skip;
347
if
(!(err =
r3d_read_reda
(s, pkt, &atom)))
348
return
0;
349
break
;
350
default
:
351
skip:
352
avio_skip
(s->
pb
, atom.
size
-8);
353
}
354
}
355
return
err;
356
}
357
358
static
int
r3d_probe
(
AVProbeData
*p)
359
{
360
if
(
AV_RL32
(p->
buf
+ 4) ==
MKTAG
(
'R'
,
'E'
,
'D'
,
'1'
))
361
return
AVPROBE_SCORE_MAX
;
362
return
0;
363
}
364
365
static
int
r3d_seek
(
AVFormatContext
*
s
,
int
stream_index, int64_t sample_time,
int
flags
)
366
{
367
AVStream
*st = s->
streams
[0];
// video stream
368
R3DContext
*r3d = s->
priv_data
;
369
int
frame_num;
370
371
if
(!st->
avg_frame_rate
.
num
)
372
return
-1;
373
374
frame_num =
av_rescale_q
(sample_time, st->
time_base
,
375
av_inv_q
(st->
avg_frame_rate
));
376
av_dlog
(s,
"seek frame num %d timestamp %"
PRId64
"\n"
,
377
frame_num, sample_time);
378
379
if
(frame_num < r3d->video_offsets_count) {
380
if
(
avio_seek
(s->
pb
, r3d->
video_offsets_count
, SEEK_SET) < 0)
381
return
-1;
382
}
else
{
383
av_log
(s,
AV_LOG_ERROR
,
"could not seek to frame %d\n"
, frame_num);
384
return
-1;
385
}
386
387
return
0;
388
}
389
390
static
int
r3d_close
(
AVFormatContext
*
s
)
391
{
392
R3DContext
*r3d = s->
priv_data
;
393
394
av_freep
(&r3d->
video_offsets
);
395
396
return
0;
397
}
398
399
AVInputFormat
ff_r3d_demuxer
= {
400
.
name
=
"r3d"
,
401
.long_name =
NULL_IF_CONFIG_SMALL
(
"REDCODE R3D"
),
402
.priv_data_size =
sizeof
(
R3DContext
),
403
.
read_probe
=
r3d_probe
,
404
.
read_header
=
r3d_read_header
,
405
.
read_packet
=
r3d_read_packet
,
406
.
read_close
=
r3d_close
,
407
.
read_seek
=
r3d_seek
,
408
};
Generated on Sat Jan 25 2014 19:52:04 for FFmpeg by
1.8.2