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