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
&& framerate.
den
) {
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
,
"negative 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 Wed Jul 10 2013 23:48:13 for FFmpeg by
1.8.2