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