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