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