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