rmdec.c 27.6 KB
Newer Older
glantau's avatar
glantau committed
1
/*
2
 * "Real" compatible demuxer.
3
 * Copyright (c) 2000, 2001 Fabrice Bellard
glantau's avatar
glantau committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
glantau's avatar
glantau committed
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
glantau's avatar
glantau committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
glantau's avatar
glantau committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
glantau's avatar
glantau committed
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
glantau's avatar
glantau committed
16
 *
glantau's avatar
glantau committed
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
glantau's avatar
glantau committed
20
 */
21 22

#include "libavutil/avstring.h"
23
#include "libavutil/intreadwrite.h"
glantau's avatar
glantau committed
24
#include "avformat.h"
25
#include "rm.h"
26

27
struct RMStream {
28
    AVPacket pkt;      ///< place to store merged video frame / reordered audio data
29 30 31 32 33 34 35 36 37
    int videobufsize;  ///< current assembled frame size
    int videobufpos;   ///< position for the next slice in the video buffer
    int curpic_num;    ///< picture number of current frame
    int cur_slice, slices;
    int64_t pktpos;    ///< first slice position in file
    /// Audio descrambling matrix parameters
    int64_t audiotimestamp; ///< Audio packet timestamp
    int sub_packet_cnt; // Subpacket counter, used while reading
    int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container
38 39 40 41 42 43 44 45 46
    int audio_framesize; /// Audio frame size from container
    int sub_packet_lengths[16]; /// Length of each subpacket
};

typedef struct {
    int nb_packets;
    int old_format;
    int current_stream;
    int remaining_len;
47 48 49
    int audio_stream_num; ///< Stream number for audio packets
    int audio_pkt_cnt; ///< Output packet counter
} RMDemuxContext;
glantau's avatar
glantau committed
50

51
static inline void get_strl(ByteIOContext *pb, char *buf, int buf_size, int len)
glantau's avatar
glantau committed
52
{
53
    int i;
54
    char *q, r;
glantau's avatar
glantau committed
55 56 57

    q = buf;
    for(i=0;i<len;i++) {
58
        r = get_byte(pb);
glantau's avatar
glantau committed
59
        if (i < buf_size - 1)
60
            *q++ = r;
glantau's avatar
glantau committed
61
    }
62
    if (buf_size > 0) *q = '\0';
glantau's avatar
glantau committed
63 64
}

65 66 67
static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
{
    get_strl(pb, buf, buf_size, get_byte(pb));
glantau's avatar
glantau committed
68 69
}

aurel's avatar
aurel committed
70 71 72 73 74 75 76 77 78 79 80
static void rm_read_metadata(AVFormatContext *s, int wide)
{
    char buf[1024];
    int i;
    for (i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
        int len = wide ? get_be16(s->pb) : get_byte(s->pb);
        get_strl(s->pb, buf, sizeof(buf), len);
        av_metadata_set(&s->metadata, ff_rm_metadata[i], buf);
    }
}

81 82 83 84 85 86 87 88 89
RMStream *ff_rm_alloc_rmstream (void)
{
    RMStream *rms = av_mallocz(sizeof(RMStream));
    rms->curpic_num = -1;
    return rms;
}

void ff_rm_free_rmstream (RMStream *rms)
{
90
    av_free_packet(&rms->pkt);
91 92
}

93
static int rm_read_audio_stream_info(AVFormatContext *s, ByteIOContext *pb,
94
                                     AVStream *st, RMStream *ast, int read_all)
95
{
96
    char buf[256];
97 98 99 100 101
    uint32_t version;

    /* ra type header */
    version = get_be32(pb); /* version */
    if (((version >> 16) & 0xff) == 3) {
102
        int64_t startpos = url_ftell(pb);
103
        url_fskip(pb, 14);
aurel's avatar
aurel committed
104
        rm_read_metadata(s, 0);
105
        if ((startpos + (version & 0xffff)) >= url_ftell(pb) + 2) {
rbultje's avatar
rbultje committed
106 107 108
            // fourcc (should always be "lpcJ")
            get_byte(pb);
            get_str8(pb, buf, sizeof(buf));
109 110 111 112
        }
        // Skip extra header crap (this should never happen)
        if ((startpos + (version & 0xffff)) > url_ftell(pb))
            url_fskip(pb, (version & 0xffff) + startpos - url_ftell(pb));
113 114 115 116
        st->codec->sample_rate = 8000;
        st->codec->channels = 1;
        st->codec->codec_type = CODEC_TYPE_AUDIO;
        st->codec->codec_id = CODEC_ID_RA_144;
117
    } else {
118
        int flavor, sub_packet_h, coded_framesize, sub_packet_size;
119 120
        /* old version (4) */
        get_be32(pb); /* .ra4 */
121 122
        get_be32(pb); /* data size */
        get_be16(pb); /* version2 */
123
        get_be32(pb); /* header size */
124
        flavor= get_be16(pb); /* add codec info / flavor */
125
        ast->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */
126 127 128
        get_be32(pb); /* ??? */
        get_be32(pb); /* ??? */
        get_be32(pb); /* ??? */
129
        ast->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */
130
        st->codec->block_align= get_be16(pb); /* frame size */
131
        ast->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */
132
        get_be16(pb); /* ??? */
133
        if (((version >> 16) & 0xff) == 5) {
134 135
            get_be16(pb); get_be16(pb); get_be16(pb);
        }
136
        st->codec->sample_rate = get_be16(pb);
137
        get_be32(pb);
138
        st->codec->channels = get_be16(pb);
139 140
        if (((version >> 16) & 0xff) == 5) {
            get_be32(pb);
141
            get_buffer(pb, buf, 4);
142 143
            buf[4] = 0;
        } else {
144 145
            get_str8(pb, buf, sizeof(buf)); /* desc */
            get_str8(pb, buf, sizeof(buf)); /* desc */
146
        }
147
        st->codec->codec_type = CODEC_TYPE_AUDIO;
148
        if (!strcmp(buf, "dnet")) {
149
            st->codec->codec_id = CODEC_ID_AC3;
150
            st->need_parsing = AVSTREAM_PARSE_FULL;
151
        } else if (!strcmp(buf, "28_8")) {
152
            st->codec->codec_id = CODEC_ID_RA_288;
153
            st->codec->extradata_size= 0;
154
            ast->audio_framesize = st->codec->block_align;
155
            st->codec->block_align = coded_framesize;
156

157 158
            if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
                av_log(s, AV_LOG_ERROR, "ast->audio_framesize * sub_packet_h too large\n");
159 160 161
                return -1;
            }

162
            av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
163
        } else if ((!strcmp(buf, "cook")) || (!strcmp(buf, "atrc")) || (!strcmp(buf, "sipr"))) {
164
            int codecdata_length;
165 166 167 168
            get_be16(pb); get_byte(pb);
            if (((version >> 16) & 0xff) == 5)
                get_byte(pb);
            codecdata_length = get_be32(pb);
169 170 171 172 173
            if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
                av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
                return -1;
            }

174 175 176 177 178
            if(sub_packet_size <= 0){
                av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n");
                return -1;
            }

banan's avatar
banan committed
179
            if (!strcmp(buf, "cook")) st->codec->codec_id = CODEC_ID_COOK;
180
            else if (!strcmp(buf, "sipr")) st->codec->codec_id = CODEC_ID_SIPR;
banan's avatar
banan committed
181
            else st->codec->codec_id = CODEC_ID_ATRAC3;
182
            st->codec->extradata_size= codecdata_length;
183
            st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
184
            get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
185 186
            ast->audio_framesize = st->codec->block_align;
            st->codec->block_align = ast->sub_packet_size;
187

188
            if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
189 190 191 192
                av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
                return -1;
            }

193
            av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
194
        } else if (!strcmp(buf, "raac") || !strcmp(buf, "racp")) {
195
            int codecdata_length;
196 197 198 199 200
            get_be16(pb); get_byte(pb);
            if (((version >> 16) & 0xff) == 5)
                get_byte(pb);
            st->codec->codec_id = CODEC_ID_AAC;
            codecdata_length = get_be32(pb);
201 202 203 204
            if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
                av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
                return -1;
            }
205 206 207 208
            if (codecdata_length >= 1) {
                st->codec->extradata_size = codecdata_length - 1;
                st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
                get_byte(pb);
209
                get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
210
            }
211
        } else {
212
            st->codec->codec_id = CODEC_ID_NONE;
mru's avatar
mru committed
213
            av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name));
214 215 216 217 218
        }
        if (read_all) {
            get_byte(pb);
            get_byte(pb);
            get_byte(pb);
aurel's avatar
aurel committed
219
            rm_read_metadata(s, 0);
220 221
        }
    }
222
    return 0;
223 224
}

225
int
226
ff_rm_read_mdpr_codecdata (AVFormatContext *s, ByteIOContext *pb,
227
                           AVStream *st, RMStream *rst, int codec_data_size)
228 229
{
    unsigned int v;
230
    int size;
231 232
    int64_t codec_pos;

233
    av_set_pts_info(st, 64, 1, 1000);
234 235 236 237
    codec_pos = url_ftell(pb);
    v = get_be32(pb);
    if (v == MKTAG(0xfd, 'a', 'r', '.')) {
        /* ra type header */
238
        if (rm_read_audio_stream_info(s, pb, st, rst, 0))
239 240 241 242 243 244 245 246 247
            return -1;
    } else {
        int fps, fps2;
        if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) {
        fail1:
            av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n");
            goto skip;
        }
        st->codec->codec_tag = get_le32(pb);
benoit's avatar
benoit committed
248
//        av_log(s, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0'));
249 250 251
        if (   st->codec->codec_tag != MKTAG('R', 'V', '1', '0')
            && st->codec->codec_tag != MKTAG('R', 'V', '2', '0')
            && st->codec->codec_tag != MKTAG('R', 'V', '3', '0')
vitor's avatar
vitor committed
252 253
            && st->codec->codec_tag != MKTAG('R', 'V', '4', '0')
            && st->codec->codec_tag != MKTAG('R', 'V', 'T', 'R'))
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
            goto fail1;
        st->codec->width = get_be16(pb);
        st->codec->height = get_be16(pb);
        st->codec->time_base.num= 1;
        fps= get_be16(pb);
        st->codec->codec_type = CODEC_TYPE_VIDEO;
        get_be32(pb);
        fps2= get_be16(pb);
        get_be16(pb);

        st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos);

        if(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){
            //check is redundant as get_buffer() will catch this
            av_log(s, AV_LOG_ERROR, "st->codec->extradata_size too large\n");
            return -1;
        }
        st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
272 273
        if (!st->codec->extradata)
            return AVERROR(ENOMEM);
274 275
        get_buffer(pb, st->codec->extradata, st->codec->extradata_size);

benoit's avatar
benoit committed
276
//        av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
        st->codec->time_base.den = fps * st->codec->time_base.num;
        switch(((uint8_t*)st->codec->extradata)[4]>>4){
        case 1: st->codec->codec_id = CODEC_ID_RV10; break;
        case 2: st->codec->codec_id = CODEC_ID_RV20; break;
        case 3: st->codec->codec_id = CODEC_ID_RV30; break;
        case 4: st->codec->codec_id = CODEC_ID_RV40; break;
        default: goto fail1;
        }
    }

skip:
    /* skip codec info */
    size = url_ftell(pb) - codec_pos;
    url_fskip(pb, codec_data_size - size);

292
    return 0;
293 294 295
}


296 297
static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
{
298
    RMDemuxContext *rm = s->priv_data;
299 300 301 302 303
    AVStream *st;

    rm->old_format = 1;
    st = av_new_stream(s, 0);
    if (!st)
304
        return -1;
305 306
    st->priv_data = ff_rm_alloc_rmstream();
    return rm_read_audio_stream_info(s, s->pb, st, st->priv_data, 1);
307 308
}

glantau's avatar
glantau committed
309 310
static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
311
    RMDemuxContext *rm = s->priv_data;
glantau's avatar
glantau committed
312
    AVStream *st;
313
    ByteIOContext *pb = s->pb;
314
    unsigned int tag;
315
    int tag_size;
316
    unsigned int start_time, duration;
glantau's avatar
glantau committed
317
    char buf[128];
318
    int flags = 0;
glantau's avatar
glantau committed
319

320 321 322 323 324
    tag = get_le32(pb);
    if (tag == MKTAG('.', 'r', 'a', 0xfd)) {
        /* very old .ra format */
        return rm_read_header_old(s, ap);
    } else if (tag != MKTAG('.', 'R', 'M', 'F')) {
325
        return AVERROR(EIO);
326
    }
glantau's avatar
glantau committed
327 328 329 330 331

    get_be32(pb); /* header size */
    get_be16(pb);
    get_be32(pb);
    get_be32(pb); /* number of headers */
332

glantau's avatar
glantau committed
333 334
    for(;;) {
        if (url_feof(pb))
335
            return -1;
glantau's avatar
glantau committed
336 337 338 339
        tag = get_le32(pb);
        tag_size = get_be32(pb);
        get_be16(pb);
#if 0
340
        printf("tag=%c%c%c%c (%08x) size=%d\n",
glantau's avatar
glantau committed
341 342 343 344 345 346 347
               (tag) & 0xff,
               (tag >> 8) & 0xff,
               (tag >> 16) & 0xff,
               (tag >> 24) & 0xff,
               tag,
               tag_size);
#endif
michael's avatar
michael committed
348
        if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A'))
349
            return -1;
glantau's avatar
glantau committed
350 351 352 353 354 355 356 357 358 359 360 361 362
        switch(tag) {
        case MKTAG('P', 'R', 'O', 'P'):
            /* file header */
            get_be32(pb); /* max bit rate */
            get_be32(pb); /* avg bit rate */
            get_be32(pb); /* max packet size */
            get_be32(pb); /* avg packet size */
            get_be32(pb); /* nb packets */
            get_be32(pb); /* duration */
            get_be32(pb); /* preroll */
            get_be32(pb); /* index offset */
            get_be32(pb); /* data offset */
            get_be16(pb); /* nb streams */
363
            flags = get_be16(pb); /* flags */
glantau's avatar
glantau committed
364 365
            break;
        case MKTAG('C', 'O', 'N', 'T'):
aurel's avatar
aurel committed
366
            rm_read_metadata(s, 1);
glantau's avatar
glantau committed
367 368
            break;
        case MKTAG('M', 'D', 'P', 'R'):
369
            st = av_new_stream(s, 0);
glantau's avatar
glantau committed
370
            if (!st)
371
                return AVERROR(ENOMEM);
glantau's avatar
glantau committed
372 373
            st->id = get_be16(pb);
            get_be32(pb); /* max bit rate */
374
            st->codec->bit_rate = get_be32(pb); /* bit rate */
glantau's avatar
glantau committed
375 376
            get_be32(pb); /* max packet size */
            get_be32(pb); /* avg packet size */
377
            start_time = get_be32(pb); /* start time */
glantau's avatar
glantau committed
378
            get_be32(pb); /* preroll */
379
            duration = get_be32(pb); /* duration */
michael's avatar
michael committed
380 381
            st->start_time = start_time;
            st->duration = duration;
glantau's avatar
glantau committed
382 383
            get_str8(pb, buf, sizeof(buf)); /* desc */
            get_str8(pb, buf, sizeof(buf)); /* mimetype */
384
            st->codec->codec_type = CODEC_TYPE_DATA;
385 386 387
            st->priv_data = ff_rm_alloc_rmstream();
            if (ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data,
                                          get_be32(pb)) < 0)
388
                return -1;
glantau's avatar
glantau committed
389 390 391 392 393 394 395 396 397 398 399
            break;
        case MKTAG('D', 'A', 'T', 'A'):
            goto header_end;
        default:
            /* unknown tag: skip it */
            url_fskip(pb, tag_size - 10);
            break;
        }
    }
 header_end:
    rm->nb_packets = get_be32(pb); /* number of packets */
400 401
    if (!rm->nb_packets && (flags & 4))
        rm->nb_packets = 3600 * 25;
glantau's avatar
glantau committed
402 403 404 405
    get_be32(pb); /* next data header */
    return 0;
}

406 407 408 409 410 411
static int get_num(ByteIOContext *pb, int *len)
{
    int n, n1;

    n = get_be16(pb);
    (*len)-=2;
412
    n &= 0x7FFF;
413 414 415 416 417 418 419 420 421
    if (n >= 0x4000) {
        return n - 0x4000;
    } else {
        n1 = get_be16(pb);
        (*len)-=2;
        return (n << 16) | n1;
    }
}

422 423 424
/* multiple of 20 bytes for ra144 (ugly) */
#define RAW_PACKET_SIZE 1000

michael's avatar
michael committed
425
static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
426
    RMDemuxContext *rm = s->priv_data;
427
    ByteIOContext *pb = s->pb;
michael's avatar
michael committed
428 429
    int len, num, res, i;
    AVStream *st;
michael's avatar
michael committed
430
    uint32_t state=0xFFFFFFFF;
michael's avatar
michael committed
431 432

    while(!url_feof(pb)){
michael's avatar
michael committed
433
        *pos= url_ftell(pb) - 3;
michael's avatar
michael committed
434 435 436 437 438 439
        if(rm->remaining_len > 0){
            num= rm->current_stream;
            len= rm->remaining_len;
            *timestamp = AV_NOPTS_VALUE;
            *flags= 0;
        }else{
michael's avatar
michael committed
440
            state= (state<<8) + get_byte(pb);
441

michael's avatar
michael committed
442 443 444 445 446 447
            if(state == MKBETAG('I', 'N', 'D', 'X')){
                len = get_be16(pb) - 6;
                if(len<0)
                    continue;
                goto skip;
            }
448

michael's avatar
michael committed
449
            if(state > (unsigned)0xFFFF || state < 12)
michael's avatar
michael committed
450
                continue;
michael's avatar
michael committed
451 452 453
            len=state;
            state= 0xFFFFFFFF;

michael's avatar
michael committed
454 455 456 457
            num = get_be16(pb);
            *timestamp = get_be32(pb);
            res= get_byte(pb); /* reserved */
            *flags = get_byte(pb); /* flags */
michael's avatar
michael committed
458

459

michael's avatar
michael committed
460 461 462 463 464 465 466 467
            len -= 12;
        }
        for(i=0;i<s->nb_streams;i++) {
            st = s->streams[i];
            if (num == st->id)
                break;
        }
        if (i == s->nb_streams) {
michael's avatar
michael committed
468
skip:
michael's avatar
michael committed
469 470
            /* skip packet if unknown number */
            url_fskip(pb, len);
rbultje's avatar
rbultje committed
471
            rm->remaining_len -= len;
michael's avatar
michael committed
472 473 474
            continue;
        }
        *stream_index= i;
475

michael's avatar
michael committed
476 477 478 479 480
        return len;
    }
    return -1;
}

481
static int rm_assemble_video_frame(AVFormatContext *s, ByteIOContext *pb,
482 483
                                   RMDemuxContext *rm, RMStream *vst,
                                   AVPacket *pkt, int len)
484 485 486 487 488 489
{
    int hdr, seq, pic_num, len2, pos;
    int type;

    hdr = get_byte(pb); len--;
    type = hdr >> 6;
490 491

    if(type != 3){  // not frame as a part of packet
492
        seq = get_byte(pb); len--;
493 494
    }
    if(type != 1){  // not whole frame
495
        len2 = get_num(pb, &len);
496
        pos  = get_num(pb, &len);
497
        pic_num = get_byte(pb); len--;
498 499 500 501 502 503 504 505
    }
    if(len<0)
        return -1;
    rm->remaining_len = len;
    if(type&1){     // frame, not slice
        if(type == 3)  // frame as a part of packet
            len= len2;
        if(rm->remaining_len < len)
506
            return -1;
507
        rm->remaining_len -= len;
508 509 510 511 512 513 514 515 516 517
        if(av_new_packet(pkt, len + 9) < 0)
            return AVERROR(EIO);
        pkt->data[0] = 0;
        AV_WL32(pkt->data + 1, 1);
        AV_WL32(pkt->data + 5, 0);
        get_buffer(pb, pkt->data + 9, len);
        return 0;
    }
    //now we have to deal with single slice

518 519 520
    if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){
        vst->slices = ((hdr & 0x3F) << 1) + 1;
        vst->videobufsize = len2 + 8*vst->slices + 1;
521 522
        av_free_packet(&vst->pkt); //FIXME this should be output.
        if(av_new_packet(&vst->pkt, vst->videobufsize) < 0)
523
            return AVERROR(ENOMEM);
524 525 526 527
        vst->videobufpos = 8*vst->slices + 1;
        vst->cur_slice = 0;
        vst->curpic_num = pic_num;
        vst->pktpos = url_ftell(pb);
528
    }
rtogni's avatar
rtogni committed
529
    if(type == 2)
530 531
        len = FFMIN(len, pos);

532
    if(++vst->cur_slice > vst->slices)
533
        return 1;
534 535
    AV_WL32(vst->pkt.data - 7 + 8*vst->cur_slice, 1);
    AV_WL32(vst->pkt.data - 3 + 8*vst->cur_slice, vst->videobufpos - 8*vst->slices - 1);
536
    if(vst->videobufpos + len > vst->videobufsize)
537
        return 1;
538
    if (get_buffer(pb, vst->pkt.data + vst->videobufpos, len) != len)
539
        return AVERROR(EIO);
540
    vst->videobufpos += len;
541 542
    rm->remaining_len-= len;

543
    if(type == 2 || (vst->videobufpos) == vst->videobufsize){
544 545
        vst->pkt.data[0] = vst->cur_slice-1;
        *pkt= vst->pkt;
cehoyos's avatar
cehoyos committed
546
        vst->pkt.data= NULL;
547 548
        vst->pkt.size= 0;
        if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin
549
            memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices,
550
                vst->videobufpos - 1 - 8*vst->slices);
551
        pkt->size = vst->videobufpos + 8*(vst->cur_slice - vst->slices);
552 553 554
        pkt->pts = AV_NOPTS_VALUE;
        pkt->pos = vst->pktpos;
        return 0;
555 556 557 558 559
    }

    return 1;
}

560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
static inline void
rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt)
{
    uint8_t *ptr;
    int j;

    if (st->codec->codec_id == CODEC_ID_AC3) {
        ptr = pkt->data;
        for (j=0;j<pkt->size;j+=2) {
            FFSWAP(int, ptr[0], ptr[1]);
            ptr += 2;
        }
    }
}

575
int
576
ff_rm_parse_packet (AVFormatContext *s, ByteIOContext *pb,
577
                    AVStream *st, RMStream *ast, int len, AVPacket *pkt,
578 579
                    int *seq, int *flags, int64_t *timestamp)
{
580
    RMDemuxContext *rm = s->priv_data;
581 582 583

    if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
        rm->current_stream= st->id;
584
        if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len))
585 586 587 588
            return -1; //got partial frame
    } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
        if ((st->codec->codec_id == CODEC_ID_RA_288) ||
            (st->codec->codec_id == CODEC_ID_COOK) ||
589 590
            (st->codec->codec_id == CODEC_ID_ATRAC3) ||
            (st->codec->codec_id == CODEC_ID_SIPR)) {
591
            int x;
592 593 594 595 596
            int sps = ast->sub_packet_size;
            int cfs = ast->coded_framesize;
            int h = ast->sub_packet_h;
            int y = ast->sub_packet_cnt;
            int w = ast->audio_framesize;
597 598

            if (*flags & 2)
599
                y = ast->sub_packet_cnt = 0;
600
            if (!y)
601
                ast->audiotimestamp = *timestamp;
602 603 604 605

            switch(st->codec->codec_id) {
                case CODEC_ID_RA_288:
                    for (x = 0; x < h/2; x++)
606
                        get_buffer(pb, ast->pkt.data+x*2*w+y*cfs, cfs);
607 608 609 610
                    break;
                case CODEC_ID_ATRAC3:
                case CODEC_ID_COOK:
                    for (x = 0; x < w/sps; x++)
611
                        get_buffer(pb, ast->pkt.data+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
612 613 614
                    break;
            }

615
            if (++(ast->sub_packet_cnt) < h)
616 617
                return -1;
            else {
618
                ast->sub_packet_cnt = 0;
619 620 621 622
                rm->audio_stream_num = st->index;
                rm->audio_pkt_cnt = h * w / st->codec->block_align - 1;
                // Release first audio packet
                av_new_packet(pkt, st->codec->block_align);
623
                memcpy(pkt->data, ast->pkt.data, st->codec->block_align); //FIXME avoid this
624
                *timestamp = ast->audiotimestamp;
625 626 627 628 629
                *flags = 2; // Mark first packet as keyframe
            }
        } else if (st->codec->codec_id == CODEC_ID_AAC) {
            int x;
            rm->audio_stream_num = st->index;
630 631 632 633
            ast->sub_packet_cnt = (get_be16(pb) & 0xf0) >> 4;
            if (ast->sub_packet_cnt) {
                for (x = 0; x < ast->sub_packet_cnt; x++)
                    ast->sub_packet_lengths[x] = get_be16(pb);
634
                // Release first audio packet
635 636
                rm->audio_pkt_cnt = ast->sub_packet_cnt - 1;
                av_get_packet(pb, pkt, ast->sub_packet_lengths[0]);
637 638
                *flags = 2; // Mark first packet as keyframe
            }
rtogni's avatar
rtogni committed
639
        } else {
640
            av_get_packet(pb, pkt, len);
641
            rm_ac3_swap_bytes(st, pkt);
rtogni's avatar
rtogni committed
642
        }
643 644 645 646 647 648 649 650 651
    } else
        av_get_packet(pb, pkt, len);

    pkt->stream_index = st->index;

#if 0
    if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
        if(st->codec->codec_id == CODEC_ID_RV20){
            int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1);
benoit's avatar
benoit committed
652
            av_log(s, AV_LOG_DEBUG, "%d %"PRId64" %d\n", *timestamp, *timestamp*512LL/25, seq);
653 654 655 656 657 658 659 660 661 662 663 664

            seq |= (*timestamp&~0x3FFF);
            if(seq - *timestamp >  0x2000) seq -= 0x4000;
            if(seq - *timestamp < -0x2000) seq += 0x4000;
        }
    }
#endif

    pkt->pts= *timestamp;
    if (*flags & 2)
        pkt->flags |= PKT_FLAG_KEY;

665
    return st->codec->codec_type == CODEC_TYPE_AUDIO ? rm->audio_pkt_cnt : 0;
666 667
}

668
int
669
ff_rm_retrieve_cache (AVFormatContext *s, ByteIOContext *pb,
670
                      AVStream *st, RMStream *ast, AVPacket *pkt)
671
{
672
    RMDemuxContext *rm = s->priv_data;
673 674 675 676

    assert (rm->audio_pkt_cnt > 0);

    if (st->codec->codec_id == CODEC_ID_AAC)
677
        av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]);
678 679
    else {
        av_new_packet(pkt, st->codec->block_align);
680
        memcpy(pkt->data, ast->pkt.data + st->codec->block_align * //FIXME avoid this
681
               (ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt),
682 683 684 685 686
               st->codec->block_align);
    }
    rm->audio_pkt_cnt--;
    pkt->flags = 0;
    pkt->stream_index = st->index;
687 688

    return rm->audio_pkt_cnt;
689 690
}

glantau's avatar
glantau committed
691 692
static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
{
693
    RMDemuxContext *rm = s->priv_data;
rbultje's avatar
rbultje committed
694
    ByteIOContext *pb = s->pb;
glantau's avatar
glantau committed
695
    AVStream *st;
rbultje's avatar
rbultje committed
696
    int i, len;
michael's avatar
michael committed
697
    int64_t timestamp, pos;
michael's avatar
michael committed
698
    int flags;
glantau's avatar
glantau committed
699

rtognimp's avatar
rtognimp committed
700
    if (rm->audio_pkt_cnt) {
701 702
        // If there are queued audio packet return them first
        st = s->streams[rm->audio_stream_num];
703
        ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt);
rtognimp's avatar
rtognimp committed
704
    } else if (rm->old_format) {
rbultje's avatar
rbultje committed
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
        RMStream *ast;

        st = s->streams[0];
        ast = st->priv_data;
        if (st->codec->codec_id == CODEC_ID_RA_288) {
            int x, y;

            for (y = 0; y < ast->sub_packet_h; y++)
                for (x = 0; x < ast->sub_packet_h/2; x++)
                    if (get_buffer(pb, ast->pkt.data+x*2*ast->audio_framesize+y*ast->coded_framesize, ast->coded_framesize) <= 0)
                        return AVERROR(EIO);
            rm->audio_stream_num = 0;
            rm->audio_pkt_cnt = ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - 1;
            // Release first audio packet
            av_new_packet(pkt, st->codec->block_align);
            memcpy(pkt->data, ast->pkt.data, st->codec->block_align); //FIXME avoid this
            pkt->flags |= PKT_FLAG_KEY; // Mark first packet as keyframe
            pkt->stream_index = 0;
        } else {
            /* just read raw bytes */
            len = RAW_PACKET_SIZE;
            len= av_get_packet(pb, pkt, len);
            pkt->stream_index = 0;
            if (len <= 0) {
                return AVERROR(EIO);
            }
            pkt->size = len;
rtognimp's avatar
rtognimp committed
732
        }
rbultje's avatar
rbultje committed
733
        rm_ac3_swap_bytes(st, pkt);
734
    } else {
rbultje's avatar
rbultje committed
735
        int seq=1;
736
resync:
michael's avatar
michael committed
737
        len=sync(s, &timestamp, &flags, &i, &pos);
michael's avatar
michael committed
738
        if(len<0)
739
            return AVERROR(EIO);
michael's avatar
michael committed
740 741
        st = s->streams[i];

742 743
        if (ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt,
                                &seq, &flags, &timestamp) < 0)
744
            goto resync;
michael's avatar
michael committed
745

746 747 748 749 750 751 752 753 754 755
        if(  (st->discard >= AVDISCARD_NONKEY && !(flags&2))
           || st->discard >= AVDISCARD_ALL){
            av_free_packet(pkt);
            while (rm->audio_pkt_cnt > 0) {
                ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt);
                av_free_packet(pkt);
            }
            goto resync;
        }

756
        if((flags&2) && (seq&0x7F) == 1)
diego's avatar
diego committed
757
            av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
758 759
    }

glantau's avatar
glantau committed
760 761 762 763 764
    return 0;
}

static int rm_read_close(AVFormatContext *s)
{
765 766 767 768
    int i;

    for (i=0;i<s->nb_streams;i++)
        ff_rm_free_rmstream(s->streams[i]->priv_data);
769

glantau's avatar
glantau committed
770 771 772
    return 0;
}

glantau's avatar
glantau committed
773 774 775
static int rm_probe(AVProbeData *p)
{
    /* check file header */
776 777 778 779 780
    if ((p->buf[0] == '.' && p->buf[1] == 'R' &&
         p->buf[2] == 'M' && p->buf[3] == 'F' &&
         p->buf[4] == 0 && p->buf[5] == 0) ||
        (p->buf[0] == '.' && p->buf[1] == 'r' &&
         p->buf[2] == 'a' && p->buf[3] == 0xfd))
glantau's avatar
glantau committed
781 782 783 784 785
        return AVPROBE_SCORE_MAX;
    else
        return 0;
}

786
static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
michael's avatar
michael committed
787 788
                               int64_t *ppos, int64_t pos_limit)
{
789
    RMDemuxContext *rm = s->priv_data;
michael's avatar
michael committed
790
    int64_t pos, dts;
michael's avatar
michael committed
791
    int stream_index2, flags, len, h;
michael's avatar
michael committed
792 793

    pos = *ppos;
794

michael's avatar
michael committed
795 796 797
    if(rm->old_format)
        return AV_NOPTS_VALUE;

798
    url_fseek(s->pb, pos, SEEK_SET);
michael's avatar
michael committed
799 800
    rm->remaining_len=0;
    for(;;){
michael's avatar
michael committed
801 802 803 804
        int seq=1;
        AVStream *st;

        len=sync(s, &dts, &flags, &stream_index2, &pos);
michael's avatar
michael committed
805 806
        if(len<0)
            return AV_NOPTS_VALUE;
michael's avatar
michael committed
807 808

        st = s->streams[stream_index2];
809
        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
810
            h= get_byte(s->pb); len--;
michael's avatar
michael committed
811
            if(!(h & 0x40)){
812
                seq = get_byte(s->pb); len--;
michael's avatar
michael committed
813 814
            }
        }
815

michael's avatar
michael committed
816
        if((flags&2) && (seq&0x7F) == 1){
817
//            av_log(s, AV_LOG_DEBUG, "%d %d-%d %"PRId64" %d\n", flags, stream_index2, stream_index, dts, seq);
michael's avatar
michael committed
818
            av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME);
michael's avatar
michael committed
819 820 821 822
            if(stream_index2 == stream_index)
                break;
        }

823
        url_fskip(s->pb, len);
michael's avatar
michael committed
824 825 826 827 828
    }
    *ppos = pos;
    return dts;
}

829
AVInputFormat rm_demuxer = {
glantau's avatar
glantau committed
830
    "rm",
831
    NULL_IF_CONFIG_SMALL("RealMedia format"),
832
    sizeof(RMDemuxContext),
glantau's avatar
glantau committed
833 834 835 836
    rm_probe,
    rm_read_header,
    rm_read_packet,
    rm_read_close,
michael's avatar
michael committed
837 838
    NULL,
    rm_read_dts,
glantau's avatar
glantau committed
839
};
840 841 842 843

AVInputFormat rdt_demuxer = {
    "rdt",
    NULL_IF_CONFIG_SMALL("RDT demuxer"),
844
    sizeof(RMDemuxContext),
845 846 847 848
    NULL,
    NULL,
    NULL,
    rm_read_close,
849
};