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
if
(st->
codec
->
sample_rate
< 0) {
289
av_log
(s,
AV_LOG_ERROR
,
"negative sample rate\n"
);
290
return
AVERROR_INVALIDDATA
;
291
}
292
293
samples =
avio_rb32
(s->
pb
);
294
295
tmp =
avio_rb32
(s->
pb
);
296
av_dlog
(s,
"packet num %d\n"
, tmp);
297
298
tmp =
avio_rb16
(s->
pb
);
// unknown
299
av_dlog
(s,
"unknown %d\n"
, tmp);
300
301
tmp =
avio_r8
(s->
pb
);
// major version
302
tmp2 =
avio_r8
(s->
pb
);
// minor version
303
av_dlog
(s,
"version %d.%d\n"
, tmp, tmp2);
304
305
tmp =
avio_rb32
(s->
pb
);
// unknown
306
av_dlog
(s,
"unknown %d\n"
, tmp);
307
308
size = atom->
size
- 8 - (
avio_tell
(s->
pb
) - pos);
309
if
(size < 0)
310
return
-1;
311
ret =
av_get_packet
(s->
pb
, pkt, size);
312
if
(ret < 0) {
313
av_log
(s,
AV_LOG_ERROR
,
"error reading audio packet\n"
);
314
return
ret;
315
}
316
317
pkt->
stream_index
= 1;
318
pkt->
dts
= dts;
319
if
(st->
codec
->
sample_rate
)
320
pkt->
duration
=
av_rescale
(samples, st->
time_base
.
den
, st->
codec
->
sample_rate
);
321
av_dlog
(s,
"pkt dts %"
PRId64
" duration %d samples %d sample rate %d\n"
,
322
pkt->
dts
, pkt->
duration
, samples, st->
codec
->
sample_rate
);
323
324
return
0;
325
}
326
327
static
int
r3d_read_packet
(
AVFormatContext
*s,
AVPacket
*
pkt
)
328
{
329
Atom
atom;
330
int
err = 0;
331
332
while
(!err) {
333
if
(
read_atom
(s, &atom) < 0) {
334
err = -1;
335
break
;
336
}
337
switch
(atom.
tag
) {
338
case
MKTAG
(
'R'
,
'E'
,
'D'
,
'V'
):
339
if
(s->
streams
[0]->
discard
==
AVDISCARD_ALL
)
340
goto
skip;
341
if
(!(err =
r3d_read_redv
(s, pkt, &atom)))
342
return
0;
343
break
;
344
case
MKTAG
(
'R'
,
'E'
,
'D'
,
'A'
):
345
if
(s->
nb_streams
< 2)
346
return
-1;
347
if
(s->
streams
[1]->
discard
==
AVDISCARD_ALL
)
348
goto
skip;
349
if
(!(err =
r3d_read_reda
(s, pkt, &atom)))
350
return
0;
351
break
;
352
default
:
353
skip:
354
avio_skip
(s->
pb
, atom.
size
-8);
355
}
356
}
357
return
err;
358
}
359
360
static
int
r3d_probe
(
AVProbeData
*p)
361
{
362
if
(
AV_RL32
(p->
buf
+ 4) ==
MKTAG
(
'R'
,
'E'
,
'D'
,
'1'
))
363
return
AVPROBE_SCORE_MAX
;
364
return
0;
365
}
366
367
static
int
r3d_seek
(
AVFormatContext
*s,
int
stream_index, int64_t sample_time,
int
flags
)
368
{
369
AVStream
*st = s->
streams
[0];
// video stream
370
R3DContext
*r3d = s->
priv_data
;
371
int
frame_num;
372
373
if
(!st->
avg_frame_rate
.
num
)
374
return
-1;
375
376
frame_num =
av_rescale_q
(sample_time, st->
time_base
,
377
av_inv_q
(st->
avg_frame_rate
));
378
av_dlog
(s,
"seek frame num %d timestamp %"
PRId64
"\n"
,
379
frame_num, sample_time);
380
381
if
(frame_num < r3d->video_offsets_count) {
382
if
(
avio_seek
(s->
pb
, r3d->
video_offsets_count
, SEEK_SET) < 0)
383
return
-1;
384
}
else
{
385
av_log
(s,
AV_LOG_ERROR
,
"could not seek to frame %d\n"
, frame_num);
386
return
-1;
387
}
388
389
return
0;
390
}
391
392
static
int
r3d_close
(
AVFormatContext
*s)
393
{
394
R3DContext
*r3d = s->
priv_data
;
395
396
av_freep
(&r3d->
video_offsets
);
397
398
return
0;
399
}
400
401
AVInputFormat
ff_r3d_demuxer
= {
402
.
name
=
"r3d"
,
403
.long_name =
NULL_IF_CONFIG_SMALL
(
"REDCODE R3D"
),
404
.priv_data_size =
sizeof
(
R3DContext
),
405
.
read_probe
=
r3d_probe
,
406
.
read_header
=
r3d_read_header
,
407
.
read_packet
=
r3d_read_packet
,
408
.
read_close
=
r3d_close
,
409
.
read_seek
=
r3d_seek
,
410
};
Generated on Sat May 25 2013 04:01:18 for FFmpeg by
1.8.2