00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "libavutil/intreadwrite.h"
00025 #include "avformat.h"
00026
00027 typedef struct {
00028 unsigned video_offsets_count;
00029 unsigned *video_offsets;
00030 unsigned rdvo_offset;
00031 } R3DContext;
00032
00033 typedef struct {
00034 unsigned size;
00035 uint32_t tag;
00036 uint64_t offset;
00037 } Atom;
00038
00039 static int read_atom(AVFormatContext *s, Atom *atom)
00040 {
00041 atom->offset = url_ftell(s->pb);
00042 atom->size = get_be32(s->pb);
00043 if (atom->size < 8)
00044 return -1;
00045 atom->tag = get_le32(s->pb);
00046 dprintf(s, "atom %d %.4s offset %#llx\n",
00047 atom->size, (char*)&atom->tag, atom->offset);
00048 return atom->size;
00049 }
00050
00051 static int r3d_read_red1(AVFormatContext *s)
00052 {
00053 AVStream *st = av_new_stream(s, 0);
00054 char filename[258];
00055 int tmp, tmp2;
00056
00057 if (!st)
00058 return -1;
00059 st->codec->codec_type = CODEC_TYPE_VIDEO;
00060 st->codec->codec_id = CODEC_ID_JPEG2000;
00061
00062 tmp = get_byte(s->pb);
00063 tmp2 = get_byte(s->pb);
00064 dprintf(s, "version %d.%d\n", tmp, tmp2);
00065
00066 tmp = get_be16(s->pb);
00067 dprintf(s, "unknown1 %d\n", tmp);
00068
00069 tmp = get_be32(s->pb);
00070 av_set_pts_info(st, 32, 1, tmp);
00071
00072 tmp = get_be32(s->pb);
00073 dprintf(s, "filenum %d\n", tmp);
00074
00075 url_fskip(s->pb, 32);
00076
00077 st->codec->width = get_be32(s->pb);
00078 st->codec->height = get_be32(s->pb);
00079
00080 tmp = get_be16(s->pb);
00081 dprintf(s, "unknown2 %d\n", tmp);
00082
00083 st->codec->time_base.den = get_be16(s->pb);
00084 st->codec->time_base.num = get_be16(s->pb);
00085
00086 tmp = get_byte(s->pb);
00087 dprintf(s, "audio channels %d\n", tmp);
00088 if (tmp > 0) {
00089 AVStream *ast = av_new_stream(s, 1);
00090 ast->codec->codec_type = CODEC_TYPE_AUDIO;
00091 ast->codec->codec_id = CODEC_ID_PCM_S32BE;
00092 ast->codec->channels = tmp;
00093 av_set_pts_info(ast, 32, 1, st->time_base.den);
00094 }
00095
00096 get_buffer(s->pb, filename, 257);
00097 filename[sizeof(filename)-1] = 0;
00098 av_metadata_set(&st->metadata, "filename", filename);
00099
00100 dprintf(s, "filename %s\n", filename);
00101 dprintf(s, "resolution %dx%d\n", st->codec->width, st->codec->height);
00102 dprintf(s, "timescale %d\n", st->time_base.den);
00103 dprintf(s, "frame rate %d/%d\n",
00104 st->codec->time_base.num, st->codec->time_base.den);
00105
00106 return 0;
00107 }
00108
00109 static int r3d_read_rdvo(AVFormatContext *s, Atom *atom)
00110 {
00111 R3DContext *r3d = s->priv_data;
00112 AVStream *st = s->streams[0];
00113 int i;
00114
00115 r3d->video_offsets_count = (atom->size - 8) / 4;
00116 r3d->video_offsets = av_malloc(atom->size);
00117 if (!r3d->video_offsets)
00118 return AVERROR(ENOMEM);
00119
00120 for (i = 0; i < r3d->video_offsets_count; i++) {
00121 r3d->video_offsets[i] = get_be32(s->pb);
00122 if (!r3d->video_offsets[i]) {
00123 r3d->video_offsets_count = i;
00124 break;
00125 }
00126 dprintf(s, "video offset %d: %#x\n", i, r3d->video_offsets[i]);
00127 }
00128
00129 if (st->codec->time_base.den)
00130 st->duration = (uint64_t)r3d->video_offsets_count*
00131 st->time_base.den*st->codec->time_base.num/st->codec->time_base.den;
00132 dprintf(s, "duration %lld\n", st->duration);
00133
00134 return 0;
00135 }
00136
00137 static void r3d_read_reos(AVFormatContext *s)
00138 {
00139 R3DContext *r3d = s->priv_data;
00140 int tmp;
00141
00142 r3d->rdvo_offset = get_be32(s->pb);
00143 get_be32(s->pb);
00144 get_be32(s->pb);
00145 get_be32(s->pb);
00146
00147 tmp = get_be32(s->pb);
00148 dprintf(s, "num video chunks %d\n", tmp);
00149
00150 tmp = get_be32(s->pb);
00151 dprintf(s, "num audio chunks %d\n", tmp);
00152
00153 url_fskip(s->pb, 6*4);
00154 }
00155
00156 static int r3d_read_header(AVFormatContext *s, AVFormatParameters *ap)
00157 {
00158 R3DContext *r3d = s->priv_data;
00159 Atom atom;
00160 int ret;
00161
00162 if (read_atom(s, &atom) < 0) {
00163 av_log(s, AV_LOG_ERROR, "error reading atom\n");
00164 return -1;
00165 }
00166 if (atom.tag == MKTAG('R','E','D','1')) {
00167 if ((ret = r3d_read_red1(s)) < 0) {
00168 av_log(s, AV_LOG_ERROR, "error parsing 'red1' atom\n");
00169 return ret;
00170 }
00171 } else {
00172 av_log(s, AV_LOG_ERROR, "could not find 'red1' atom\n");
00173 return -1;
00174 }
00175
00176 s->data_offset = url_ftell(s->pb);
00177 dprintf(s, "data offset %#llx\n", s->data_offset);
00178 if (url_is_streamed(s->pb))
00179 return 0;
00180
00181 url_fseek(s->pb, url_fsize(s->pb)-48-8, SEEK_SET);
00182 if (read_atom(s, &atom) < 0)
00183 av_log(s, AV_LOG_ERROR, "error reading end atom\n");
00184
00185 if (atom.tag != MKTAG('R','E','O','B') &&
00186 atom.tag != MKTAG('R','E','O','F') &&
00187 atom.tag != MKTAG('R','E','O','S'))
00188 goto out;
00189
00190 r3d_read_reos(s);
00191
00192 if (r3d->rdvo_offset) {
00193 url_fseek(s->pb, r3d->rdvo_offset, SEEK_SET);
00194 if (read_atom(s, &atom) < 0)
00195 av_log(s, AV_LOG_ERROR, "error reading 'rdvo' atom\n");
00196 if (atom.tag == MKTAG('R','D','V','O')) {
00197 if (r3d_read_rdvo(s, &atom) < 0)
00198 av_log(s, AV_LOG_ERROR, "error parsing 'rdvo' atom\n");
00199 }
00200 }
00201
00202 out:
00203 url_fseek(s->pb, s->data_offset, SEEK_SET);
00204 return 0;
00205 }
00206
00207 static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom)
00208 {
00209 AVStream *st = s->streams[0];
00210 int tmp, tmp2;
00211 uint64_t pos = url_ftell(s->pb);
00212 unsigned dts;
00213
00214 dts = get_be32(s->pb);
00215
00216 tmp = get_be32(s->pb);
00217 dprintf(s, "frame num %d\n", tmp);
00218
00219 tmp = get_byte(s->pb);
00220 tmp2 = get_byte(s->pb);
00221 dprintf(s, "version %d.%d\n", tmp, tmp2);
00222
00223 tmp = get_be16(s->pb);
00224 dprintf(s, "unknown %d\n", tmp);
00225
00226 if (tmp > 4) {
00227 tmp = get_be16(s->pb);
00228 dprintf(s, "unknown %d\n", tmp);
00229
00230 tmp = get_be16(s->pb);
00231 dprintf(s, "unknown %d\n", tmp);
00232
00233 tmp = get_be32(s->pb);
00234 dprintf(s, "width %d\n", tmp);
00235 tmp = get_be32(s->pb);
00236 dprintf(s, "height %d\n", tmp);
00237
00238 tmp = get_be32(s->pb);
00239 dprintf(s, "metadata len %d\n", tmp);
00240 }
00241 tmp = atom->size - 8 - (url_ftell(s->pb) - pos);
00242 if (tmp < 0)
00243 return -1;
00244
00245 if (av_get_packet(s->pb, pkt, tmp) != tmp) {
00246 av_log(s, AV_LOG_ERROR, "error reading video packet\n");
00247 return -1;
00248 }
00249
00250 pkt->stream_index = 0;
00251 pkt->dts = dts;
00252 if (st->codec->time_base.den)
00253 pkt->duration = (uint64_t)st->time_base.den*
00254 st->codec->time_base.num/st->codec->time_base.den;
00255 dprintf(s, "pkt dts %lld duration %d\n", pkt->dts, pkt->duration);
00256
00257 return 0;
00258 }
00259
00260 static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom)
00261 {
00262 AVStream *st = s->streams[1];
00263 int tmp, tmp2, samples, size;
00264 uint64_t pos = url_ftell(s->pb);
00265 unsigned dts;
00266
00267 dts = get_be32(s->pb);
00268
00269 st->codec->sample_rate = get_be32(s->pb);
00270
00271 samples = get_be32(s->pb);
00272
00273 tmp = get_be32(s->pb);
00274 dprintf(s, "packet num %d\n", tmp);
00275
00276 tmp = get_be16(s->pb);
00277 dprintf(s, "unknown %d\n", tmp);
00278
00279 tmp = get_byte(s->pb);
00280 tmp2 = get_byte(s->pb);
00281 dprintf(s, "version %d.%d\n", tmp, tmp2);
00282
00283 tmp = get_be32(s->pb);
00284 dprintf(s, "unknown %d\n", tmp);
00285
00286 size = atom->size - 8 - (url_ftell(s->pb) - pos);
00287 if (size < 0)
00288 return -1;
00289 if (av_get_packet(s->pb, pkt, size) != size) {
00290 av_log(s, AV_LOG_ERROR, "error reading video packet\n");
00291 return -1;
00292 }
00293
00294 pkt->stream_index = 1;
00295 pkt->dts = dts;
00296 pkt->duration = av_rescale(samples, st->time_base.den, st->codec->sample_rate);
00297 dprintf(s, "pkt dts %lld duration %d samples %d sample rate %d\n",
00298 pkt->dts, pkt->duration, samples, st->codec->sample_rate);
00299
00300 return 0;
00301 }
00302
00303 static int r3d_read_packet(AVFormatContext *s, AVPacket *pkt)
00304 {
00305 Atom atom;
00306 int err = 0;
00307
00308 while (!err) {
00309 if (read_atom(s, &atom) < 0) {
00310 err = -1;
00311 break;
00312 }
00313 switch (atom.tag) {
00314 case MKTAG('R','E','D','V'):
00315 if (s->streams[0]->discard == AVDISCARD_ALL)
00316 goto skip;
00317 if (!(err = r3d_read_redv(s, pkt, &atom)))
00318 return 0;
00319 break;
00320 case MKTAG('R','E','D','A'):
00321 if (s->nb_streams < 2)
00322 return -1;
00323 if (s->streams[1]->discard == AVDISCARD_ALL)
00324 goto skip;
00325 if (!(err = r3d_read_reda(s, pkt, &atom)))
00326 return 0;
00327 break;
00328 default:
00329 skip:
00330 url_fskip(s->pb, atom.size-8);
00331 }
00332 }
00333 return err;
00334 }
00335
00336 static int r3d_probe(AVProbeData *p)
00337 {
00338 if (AV_RL32(p->buf + 4) == MKTAG('R','E','D','1'))
00339 return AVPROBE_SCORE_MAX;
00340 return 0;
00341 }
00342
00343 static int r3d_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
00344 {
00345 AVStream *st = s->streams[0];
00346 R3DContext *r3d = s->priv_data;
00347 int frame_num;
00348
00349 if (!st->codec->time_base.num || !st->time_base.den)
00350 return -1;
00351
00352 frame_num = sample_time*st->codec->time_base.den/
00353 ((int64_t)st->codec->time_base.num*st->time_base.den);
00354 dprintf(s, "seek frame num %d timestamp %lld\n", frame_num, sample_time);
00355
00356 if (frame_num < r3d->video_offsets_count) {
00357 url_fseek(s->pb, r3d->video_offsets_count, SEEK_SET);
00358 } else {
00359 av_log(s, AV_LOG_ERROR, "could not seek to frame %d\n", frame_num);
00360 return -1;
00361 }
00362
00363 return 0;
00364 }
00365
00366 static int r3d_close(AVFormatContext *s)
00367 {
00368 R3DContext *r3d = s->priv_data;
00369
00370 av_freep(&r3d->video_offsets);
00371
00372 return 0;
00373 }
00374
00375 AVInputFormat r3d_demuxer = {
00376 "r3d",
00377 NULL_IF_CONFIG_SMALL("REDCODE R3D format"),
00378 sizeof(R3DContext),
00379 r3d_probe,
00380 r3d_read_header,
00381 r3d_read_packet,
00382 r3d_close,
00383 r3d_seek,
00384 };