FFmpeg
Loading...
Searching...
No Matches
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
23#include "libavutil/dict.h"
25#include "avformat.h"
26#include "demux.h"
27#include "internal.h"
28
29typedef struct R3DContext {
31 unsigned rdvo_offset;
32
35
36typedef struct Atom {
37 unsigned size;
38 uint32_t tag;
39 uint64_t offset;
40} Atom;
41
42static 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_log(s, AV_LOG_TRACE, "atom %u %.4s offset %#"PRIx64"\n",
50 atom->size, (char*)&atom->tag, atom->offset);
51 return atom->size;
52}
53
55{
57 R3DContext *r3d = s->priv_data;
58 char filename[258];
59 int tmp;
60 int ret;
61 av_unused int tmp2;
63
64 if (!st)
65 return AVERROR(ENOMEM);
68
69 tmp = avio_r8(s->pb); // major version
70 tmp2 = avio_r8(s->pb); // minor version
71 av_log(s, AV_LOG_TRACE, "version %d.%d\n", tmp, tmp2);
72
73 tmp = avio_rb16(s->pb); // unknown
74 av_log(s, AV_LOG_TRACE, "unknown1 %d\n", tmp);
75
76 tmp = avio_rb32(s->pb);
77 avpriv_set_pts_info(st, 32, 1, tmp);
78
79 tmp = avio_rb32(s->pb); // filenum
80 av_log(s, AV_LOG_TRACE, "filenum %d\n", tmp);
81
82 avio_skip(s->pb, 32); // unknown
83
84 st->codecpar->width = avio_rb32(s->pb);
85 st->codecpar->height = avio_rb32(s->pb);
86
87 tmp = avio_rb16(s->pb); // unknown
88 av_log(s, AV_LOG_TRACE, "unknown2 %d\n", tmp);
89
90 framerate.num = avio_rb16(s->pb);
91 framerate.den = avio_rb16(s->pb);
92 if (framerate.num > 0 && framerate.den > 0) {
93#if FF_API_R_FRAME_RATE
94 st->r_frame_rate =
95#endif
97 }
98
99 r3d->audio_channels = avio_r8(s->pb); // audio channels
100 av_log(s, AV_LOG_TRACE, "audio channels %d\n", tmp);
101
102 ret = avio_read(s->pb, filename, 257);
103 if (ret < 257)
104 return ret < 0 ? ret : AVERROR_EOF;
105 filename[sizeof(filename)-1] = 0;
106 av_dict_set(&st->metadata, "filename", filename, 0);
107
108 av_log(s, AV_LOG_TRACE, "filename %s\n", filename);
109 av_log(s, AV_LOG_TRACE, "resolution %dx%d\n", st->codecpar->width, st->codecpar->height);
110 av_log(s, AV_LOG_TRACE, "timescale %d\n", st->time_base.den);
111 av_log(s, AV_LOG_TRACE, "frame rate %d/%d\n",
112 framerate.num, framerate.den);
113
114 return 0;
115}
116
118{
119 R3DContext *r3d = s->priv_data;
120 AVStream *st = s->streams[0];
121 int i;
122
123 r3d->video_offsets_count = (atom->size - 8) / 4;
124
125 for (i = 0; i < r3d->video_offsets_count; i++) {
126 unsigned video_offset = avio_rb32(s->pb);
127 if (!video_offset) {
128 r3d->video_offsets_count = i;
129 break;
130 }
131 av_log(s, AV_LOG_TRACE, "video offset %d: %#x\n", i, video_offset);
132 }
133
134 if (st->avg_frame_rate.num)
137 st->time_base);
138 av_log(s, AV_LOG_TRACE, "duration %"PRId64"\n", st->duration);
139
140 return 0;
141}
142
144{
145 R3DContext *r3d = s->priv_data;
146 av_unused int tmp;
147
148 r3d->rdvo_offset = avio_rb32(s->pb);
149 avio_rb32(s->pb); // rdvs offset
150 avio_rb32(s->pb); // rdao offset
151 avio_rb32(s->pb); // rdas offset
152
153 tmp = avio_rb32(s->pb);
154 av_log(s, AV_LOG_TRACE, "num video chunks %d\n", tmp);
155
156 tmp = avio_rb32(s->pb);
157 av_log(s, AV_LOG_TRACE, "num audio chunks %d\n", tmp);
158
159 avio_skip(s->pb, 6*4);
160}
161
163{
164 FFFormatContext *const si = ffformatcontext(s);
165 R3DContext *r3d = s->priv_data;
166 Atom atom;
167 int ret;
168
169 if (read_atom(s, &atom) < 0) {
170 av_log(s, AV_LOG_ERROR, "error reading atom\n");
171 return -1;
172 }
173 if (atom.tag == MKTAG('R','E','D','1')) {
174 if ((ret = r3d_read_red1(s)) < 0) {
175 av_log(s, AV_LOG_ERROR, "error parsing 'red1' atom\n");
176 return ret;
177 }
178 } else {
179 av_log(s, AV_LOG_ERROR, "could not find 'red1' atom\n");
180 return -1;
181 }
182
183 /* we cannot create the audio stream now because we do not know the
184 * sample rate */
185 if (r3d->audio_channels)
186 s->ctx_flags |= AVFMTCTX_NOHEADER;
187
188 si->data_offset = avio_tell(s->pb);
189 av_log(s, AV_LOG_TRACE, "data offset %#"PRIx64"\n", si->data_offset);
190 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
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
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, si->data_offset, SEEK_SET);
216 return 0;
217}
218
220{
221 AVStream *st = s->streams[0];
222 int tmp;
223 av_unused int tmp2;
224 int64_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_log(s, AV_LOG_TRACE, "frame num %d\n", tmp);
232
233 tmp = avio_r8(s->pb); // major version
234 tmp2 = avio_r8(s->pb); // minor version
235 av_log(s, AV_LOG_TRACE, "version %d.%d\n", tmp, tmp2);
236
237 tmp = avio_rb16(s->pb); // unknown
238 av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp);
239
240 if (tmp > 4) {
241 tmp = avio_rb16(s->pb); // unknown
242 av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp);
243
244 tmp = avio_rb16(s->pb); // unknown
245 av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp);
246
247 tmp = avio_rb32(s->pb);
248 av_log(s, AV_LOG_TRACE, "width %d\n", tmp);
249 tmp = avio_rb32(s->pb);
250 av_log(s, AV_LOG_TRACE, "height %d\n", tmp);
251
252 tmp = avio_rb32(s->pb);
253 av_log(s, AV_LOG_TRACE, "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*
269 av_log(s, AV_LOG_TRACE, "pkt dts %"PRId64" duration %"PRId64"\n", pkt->dts, pkt->duration);
270
271 return 0;
272}
273
275{
276 R3DContext *r3d = s->priv_data;
277 AVStream *st;
278 av_unused int tmp, tmp2;
279 int samples, size;
280 int64_t pos = avio_tell(s->pb);
281 unsigned dts;
282 int ret;
283
284 if (s->nb_streams < 2) {
286 if (!st)
287 return AVERROR(ENOMEM);
291 avpriv_set_pts_info(st, 32, 1, s->streams[0]->time_base.den);
292 } else {
293 st = s->streams[1];
294 }
295
296 dts = avio_rb32(s->pb);
297
298 st->codecpar->sample_rate = avio_rb32(s->pb);
299 if (st->codecpar->sample_rate <= 0) {
300 av_log(s, AV_LOG_ERROR, "Bad sample rate\n");
301 return AVERROR_INVALIDDATA;
302 }
303
304 samples = avio_rb32(s->pb);
305
306 tmp = avio_rb32(s->pb);
307 av_log(s, AV_LOG_TRACE, "packet num %d\n", tmp);
308
309 tmp = avio_rb16(s->pb); // unknown
310 av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp);
311
312 tmp = avio_r8(s->pb); // major version
313 tmp2 = avio_r8(s->pb); // minor version
314 av_log(s, AV_LOG_TRACE, "version %d.%d\n", tmp, tmp2);
315
316 tmp = avio_rb32(s->pb); // unknown
317 av_log(s, AV_LOG_TRACE, "unknown %d\n", tmp);
318
319 size = atom->size - 8 - (avio_tell(s->pb) - pos);
320 if (size < 0)
321 return -1;
322 ret = av_get_packet(s->pb, pkt, size);
323 if (ret < 0) {
324 av_log(s, AV_LOG_ERROR, "error reading audio packet\n");
325 return ret;
326 }
327
328 pkt->stream_index = 1;
329 pkt->dts = dts;
330
331 if (st->codecpar->sample_rate && samples > 0)
332 pkt->duration = av_rescale(samples, st->time_base.den, st->codecpar->sample_rate);
333 av_log(s, AV_LOG_TRACE, "pkt dts %"PRId64" duration %"PRId64" samples %d sample rate %d\n",
334 pkt->dts, pkt->duration, samples, st->codecpar->sample_rate);
335
336 return 0;
337}
338
340{
341 R3DContext *r3d = s->priv_data;
342 Atom atom;
343 int err = 0;
344
345 while (!err) {
346 if (read_atom(s, &atom) < 0) {
347 err = -1;
348 break;
349 }
350 switch (atom.tag) {
351 case MKTAG('R','E','D','V'):
352 if (s->streams[0]->discard == AVDISCARD_ALL)
353 goto skip;
354 if (!(err = r3d_read_redv(s, pkt, &atom)))
355 return 0;
356 break;
357 case MKTAG('R','E','D','A'):
358 if (!r3d->audio_channels)
359 return -1;
360 if (s->nb_streams >= 2 && s->streams[1]->discard == AVDISCARD_ALL)
361 goto skip;
362 if (!(err = r3d_read_reda(s, pkt, &atom)))
363 return 0;
364 break;
365 default:
366 skip:
367 avio_skip(s->pb, atom.size-8);
368 }
369 }
370 return err;
371}
372
373static int r3d_probe(const AVProbeData *p)
374{
375 if (AV_RL32(p->buf + 4) == MKTAG('R','E','D','1'))
376 return AVPROBE_SCORE_MAX;
377 return 0;
378}
379
380static int r3d_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
381{
382 AVStream *st = s->streams[0]; // video stream
383 R3DContext *r3d = s->priv_data;
384 int frame_num;
385
386 if (!st->avg_frame_rate.num)
387 return -1;
388
389 frame_num = av_rescale_q(sample_time, st->time_base,
391 av_log(s, AV_LOG_TRACE, "seek frame num %d timestamp %"PRId64"\n",
392 frame_num, sample_time);
393
394 if (frame_num < r3d->video_offsets_count) {
395 if (avio_seek(s->pb, r3d->video_offsets_count, SEEK_SET) < 0)
396 return -1;
397 } else {
398 av_log(s, AV_LOG_ERROR, "could not seek to frame %d\n", frame_num);
399 return -1;
400 }
401
402 return 0;
403}
404
406 .p.name = "r3d",
407 .p.long_name = NULL_IF_CONFIG_SMALL("REDCODE R3D"),
408 .priv_data_size = sizeof(R3DContext),
413};
const FFInputFormat ff_r3d_demuxer
Definition r3d.c:405
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
#define AVPROBE_SCORE_MAX
maximum score
Definition avformat.h:483
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition avformat.h:1284
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition utils.c:98
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
#define AVIO_SEEKABLE_NORMAL
Seeking works like for a local file.
Definition avio.h:41
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition aviobuf.c:326
unsigned int avio_rb16(AVIOContext *s)
Definition aviobuf.c:749
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition aviobuf.c:321
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition aviobuf.c:615
unsigned int avio_rl32(AVIOContext *s)
Definition aviobuf.c:733
unsigned int avio_rb32(AVIOContext *s)
Definition aviobuf.c:764
int avio_r8(AVIOContext *s)
Definition aviobuf.c:606
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
static int read_probe(const AVProbeData *p)
Definition cdg.c:30
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVPacket * pkt
Public dictionary API.
static int read_header(FFV1Context *f, RangeCoder *c)
Definition ffv1dec.c:578
@ AV_CODEC_ID_JPEG2000
Definition codec_id.h:138
@ AV_CODEC_ID_PCM_S32BE
Definition codec_id.h:339
@ AVDISCARD_ALL
discard all
Definition defs.h:232
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define AV_RL32(p)
static av_always_inline FFFormatContext * ffformatcontext(AVFormatContext *s)
Definition internal.h:130
#define av_unused
Definition attributes.h:164
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition libcdio.c:151
#define MKTAG(a, b, c, d)
Definition macros.h:55
static int r3d_read_red1(AVFormatContext *s)
Definition r3d.c:54
static int r3d_read_rdvo(AVFormatContext *s, Atom *atom)
Definition r3d.c:117
static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom)
Definition r3d.c:219
static int read_atom(AVFormatContext *s, Atom *atom)
Definition r3d.c:42
static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom)
Definition r3d.c:274
static int r3d_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
Definition r3d.c:380
static void r3d_read_reos(AVFormatContext *s)
Definition r3d.c:143
static int r3d_read_header(AVFormatContext *s)
Definition r3d.c:162
static int r3d_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition r3d.c:339
static int r3d_probe(const AVProbeData *p)
Definition r3d.c:373
unsigned int pos
Definition spdifenc.c:431
int nb_channels
Number of channels in this layout.
int height
The height of the video frame in pixels.
Definition codec_par.h:150
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
int width
The width of the video frame in pixels.
Definition codec_par.h:143
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
Format I/O context.
Definition avformat.h:1333
This structure stores compressed data.
Definition packet.h:580
This structure contains the data a format has to probe a file.
Definition avformat.h:471
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition avformat.h:825
AVDictionary * metadata
Definition avformat.h:846
AVRational avg_frame_rate
Average framerate.
Definition avformat.h:855
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:805
AVRational r_frame_rate
Real base framerate of the stream.
Definition avformat.h:900
Definition r3d.c:36
unsigned size
Definition r3d.c:37
uint64_t offset
Definition r3d.c:39
uint32_t tag
Definition r3d.c:38
int64_t data_offset
offset of the first packet
Definition internal.h:89
unsigned video_offsets_count
Definition r3d.c:30
int audio_channels
Definition r3d.c:33
unsigned rdvo_offset
Definition r3d.c:31
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
float framerate
Definition av1_levels.c:29
static FILE * out
Definition movenc.c:55
int size