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

#include "libavutil/avstring.h"
23
#include "libavutil/intreadwrite.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
24
#include "avformat.h"
25
#include "riff.h"
26
#include "rm.h"
27

28
struct RMStream {
29
    AVPacket pkt;      ///< place to store merged video frame / reordered audio data
30 31 32 33 34 35 36 37 38
    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
39 40 41 42 43 44 45 46 47
    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;
48 49 50
    int audio_stream_num; ///< Stream number for audio packets
    int audio_pkt_cnt; ///< Output packet counter
} RMDemuxContext;
Fabrice Bellard's avatar
Fabrice Bellard committed
51

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
static const AVCodecTag rm_codec_tags[] = {
    { CODEC_ID_RV10,   MKTAG('R','V','1','0') },
    { CODEC_ID_RV20,   MKTAG('R','V','2','0') },
    { CODEC_ID_RV20,   MKTAG('R','V','T','R') },
    { CODEC_ID_RV30,   MKTAG('R','V','3','0') },
    { CODEC_ID_RV40,   MKTAG('R','V','4','0') },
    { CODEC_ID_AC3,    MKTAG('d','n','e','t') },
    { CODEC_ID_RA_144, MKTAG('l','p','c','J') },
    { CODEC_ID_RA_288, MKTAG('2','8','_','8') },
    { CODEC_ID_COOK,   MKTAG('c','o','o','k') },
    { CODEC_ID_ATRAC3, MKTAG('a','t','r','c') },
    { CODEC_ID_SIPR,   MKTAG('s','i','p','r') },
    { CODEC_ID_AAC,    MKTAG('r','a','a','c') },
    { CODEC_ID_AAC,    MKTAG('r','a','c','p') },
    { 0 },
};

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
static const unsigned char sipr_swaps[38][2] = {
    {  0, 63 }, {  1, 22 }, {  2, 44 }, {  3, 90 },
    {  5, 81 }, {  7, 31 }, {  8, 86 }, {  9, 58 },
    { 10, 36 }, { 12, 68 }, { 13, 39 }, { 14, 73 },
    { 15, 53 }, { 16, 69 }, { 17, 57 }, { 19, 88 },
    { 20, 34 }, { 21, 71 }, { 24, 46 }, { 25, 94 },
    { 26, 54 }, { 28, 75 }, { 29, 50 }, { 32, 70 },
    { 33, 92 }, { 35, 74 }, { 38, 85 }, { 40, 56 },
    { 42, 87 }, { 43, 65 }, { 45, 59 }, { 48, 79 },
    { 49, 93 }, { 51, 89 }, { 55, 95 }, { 61, 76 },
    { 67, 83 }, { 77, 80 }
};

static const unsigned char sipr_subpk_size[4] = { 29, 19, 37, 20 };

84
static inline void get_strl(ByteIOContext *pb, char *buf, int buf_size, int len)
Fabrice Bellard's avatar
Fabrice Bellard committed
85
{
86
    int i;
87
    char *q, r;
Fabrice Bellard's avatar
Fabrice Bellard committed
88 89 90

    q = buf;
    for(i=0;i<len;i++) {
91
        r = get_byte(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
92
        if (i < buf_size - 1)
93
            *q++ = r;
Fabrice Bellard's avatar
Fabrice Bellard committed
94
    }
95
    if (buf_size > 0) *q = '\0';
Fabrice Bellard's avatar
Fabrice Bellard committed
96 97
}

98 99 100
static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
{
    get_strl(pb, buf, buf_size, get_byte(pb));
Fabrice Bellard's avatar
Fabrice Bellard committed
101 102
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116
static int rm_read_extradata(ByteIOContext *pb, AVCodecContext *avctx, unsigned size)
{
    if (size >= 1<<24)
        return -1;
    avctx->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!avctx->extradata)
        return AVERROR_NOMEM;
    avctx->extradata_size = get_buffer(pb, avctx->extradata, size);
    memset(avctx->extradata + avctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
    if (avctx->extradata_size != size)
        return AVERROR(EIO);
    return 0;
}

117 118 119 120 121 122 123 124 125 126 127
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);
    }
}

128 129 130 131 132 133 134 135 136
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)
{
137
    av_free_packet(&rms->pkt);
138 139
}

140
static int rm_read_audio_stream_info(AVFormatContext *s, ByteIOContext *pb,
141
                                     AVStream *st, RMStream *ast, int read_all)
142
{
143
    char buf[256];
144
    uint32_t version;
145
    int ret;
146 147

    /* ra type header */
148 149 150
    version = get_be16(pb); /* version */
    if (version == 3) {
        int header_size = get_be16(pb);
151
        int64_t startpos = url_ftell(pb);
152
        url_fskip(pb, 14);
153
        rm_read_metadata(s, 0);
154
        if ((startpos + header_size) >= url_ftell(pb) + 2) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
155 156 157
            // fourcc (should always be "lpcJ")
            get_byte(pb);
            get_str8(pb, buf, sizeof(buf));
158 159
        }
        // Skip extra header crap (this should never happen)
160 161
        if ((startpos + header_size) > url_ftell(pb))
            url_fskip(pb, header_size + startpos - url_ftell(pb));
162 163 164 165
        st->codec->sample_rate = 8000;
        st->codec->channels = 1;
        st->codec->codec_type = CODEC_TYPE_AUDIO;
        st->codec->codec_id = CODEC_ID_RA_144;
166
    } else {
167
        int flavor, sub_packet_h, coded_framesize, sub_packet_size;
168
        int codecdata_length;
169
        /* old version (4) */
170
        url_fskip(pb, 2); /* unused */
171
        get_be32(pb); /* .ra4 */
172 173
        get_be32(pb); /* data size */
        get_be16(pb); /* version2 */
174
        get_be32(pb); /* header size */
175
        flavor= get_be16(pb); /* add codec info / flavor */
176
        ast->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */
177 178 179
        get_be32(pb); /* ??? */
        get_be32(pb); /* ??? */
        get_be32(pb); /* ??? */
180
        ast->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */
181
        st->codec->block_align= get_be16(pb); /* frame size */
182
        ast->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */
183
        get_be16(pb); /* ??? */
184
        if (version == 5) {
185 186
            get_be16(pb); get_be16(pb); get_be16(pb);
        }
187
        st->codec->sample_rate = get_be16(pb);
188
        get_be32(pb);
189
        st->codec->channels = get_be16(pb);
190
        if (version == 5) {
191
            get_be32(pb);
192
            get_buffer(pb, buf, 4);
193 194
            buf[4] = 0;
        } else {
195 196
            get_str8(pb, buf, sizeof(buf)); /* desc */
            get_str8(pb, buf, sizeof(buf)); /* desc */
197
        }
198
        st->codec->codec_type = CODEC_TYPE_AUDIO;
199 200 201 202
        st->codec->codec_tag  = AV_RL32(buf);
        st->codec->codec_id   = ff_codec_get_id(rm_codec_tags, st->codec->codec_tag);
        switch (st->codec->codec_id) {
        case CODEC_ID_AC3:
203
            st->need_parsing = AVSTREAM_PARSE_FULL;
204 205
            break;
        case CODEC_ID_RA_288:
206
            st->codec->extradata_size= 0;
207
            ast->audio_framesize = st->codec->block_align;
208
            st->codec->block_align = coded_framesize;
209

210 211
            if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
                av_log(s, AV_LOG_ERROR, "ast->audio_framesize * sub_packet_h too large\n");
212 213 214
                return -1;
            }

215
            av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
216 217 218 219
            break;
        case CODEC_ID_COOK:
        case CODEC_ID_ATRAC3:
        case CODEC_ID_SIPR:
220
            get_be16(pb); get_byte(pb);
221
            if (version == 5)
222 223
                get_byte(pb);
            codecdata_length = get_be32(pb);
224 225 226 227 228
            if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
                av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
                return -1;
            }

Benjamin Larsson's avatar
Benjamin Larsson committed
229
            if (!strcmp(buf, "cook")) st->codec->codec_id = CODEC_ID_COOK;
230
            else if (!strcmp(buf, "sipr")) st->codec->codec_id = CODEC_ID_SIPR;
Benjamin Larsson's avatar
Benjamin Larsson committed
231
            else st->codec->codec_id = CODEC_ID_ATRAC3;
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247

            ast->audio_framesize = st->codec->block_align;
            if (st->codec->codec_id == CODEC_ID_SIPR) {
                if (flavor > 3) {
                    av_log(s, AV_LOG_ERROR, "bad SIPR file flavor %d\n",
                           flavor);
                    return -1;
                }
                st->codec->block_align = sipr_subpk_size[flavor];
            } else {
                if(sub_packet_size <= 0){
                    av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n");
                    return -1;
                }
                st->codec->block_align = ast->sub_packet_size;
            }
248 249
            if ((ret = rm_read_extradata(s->pb, st->codec, codecdata_length)) < 0)
                return ret;
250

251
            if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
252 253 254 255
                av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
                return -1;
            }

256
            av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
257 258
            break;
        case CODEC_ID_AAC:
259
            get_be16(pb); get_byte(pb);
260
            if (version == 5)
261 262 263
                get_byte(pb);
            st->codec->codec_id = CODEC_ID_AAC;
            codecdata_length = get_be32(pb);
264 265 266 267
            if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){
                av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
                return -1;
            }
268 269
            if (codecdata_length >= 1) {
                get_byte(pb);
270 271
                if ((ret = rm_read_extradata(s->pb, st->codec, codecdata_length - 1)) < 0)
                    return ret;
272
            }
273 274
            break;
        default:
Måns Rullgård's avatar
Måns Rullgård committed
275
            av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name));
276 277 278 279 280
        }
        if (read_all) {
            get_byte(pb);
            get_byte(pb);
            get_byte(pb);
281
            rm_read_metadata(s, 0);
282 283
        }
    }
284
    return 0;
285 286
}

287
int
288
ff_rm_read_mdpr_codecdata (AVFormatContext *s, ByteIOContext *pb,
289
                           AVStream *st, RMStream *rst, int codec_data_size)
290 291
{
    unsigned int v;
292
    int size;
293
    int64_t codec_pos;
294
    int ret;
295

296
    av_set_pts_info(st, 64, 1, 1000);
297 298 299 300
    codec_pos = url_ftell(pb);
    v = get_be32(pb);
    if (v == MKTAG(0xfd, 'a', 'r', '.')) {
        /* ra type header */
301
        if (rm_read_audio_stream_info(s, pb, st, rst, 0))
302 303 304 305 306 307 308 309 310
            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);
311
        st->codec->codec_id  = ff_codec_get_id(rm_codec_tags, st->codec->codec_tag);
312
//        av_log(s, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0'));
313
        if (st->codec->codec_id == CODEC_ID_NONE)
314 315 316 317 318 319 320 321 322 323
            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);

324 325
        if ((ret = rm_read_extradata(s->pb, st->codec, codec_data_size - (url_ftell(pb) - codec_pos))) < 0)
            return ret;
326

327
//        av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
328
        st->codec->time_base.den = fps * st->codec->time_base.num;
329
        //XXX: do we really need that?
330 331 332 333 334 335 336 337 338 339 340 341 342 343
        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);

344
    return 0;
345 346
}

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
/** this function assumes that the demuxer has already seeked to the start
 * of the INDX chunk, and will bail out if not. */
static int rm_read_index(AVFormatContext *s)
{
    ByteIOContext *pb = s->pb;
    unsigned int size, n_pkts, str_id, next_off, n, pos, pts;
    AVStream *st;

    do {
        if (get_le32(pb) != MKTAG('I','N','D','X'))
            return -1;
        size     = get_be32(pb);
        if (size < 20)
            return -1;
        url_fskip(pb, 2);
        n_pkts   = get_be32(pb);
        str_id   = get_be16(pb);
        next_off = get_be32(pb);
        for (n = 0; n < s->nb_streams; n++)
            if (s->streams[n]->id == str_id) {
                st = s->streams[n];
                break;
            }
        if (n == s->nb_streams)
            goto skip;

        for (n = 0; n < n_pkts; n++) {
            url_fskip(pb, 2);
            pts = get_be32(pb);
            pos = get_be32(pb);
            url_fskip(pb, 4); /* packet no. */

            av_add_index_entry(st, pos, pts, 0, 0, AVINDEX_KEYFRAME);
        }

skip:
        if (next_off && url_ftell(pb) != next_off &&
            url_fseek(pb, next_off, SEEK_SET) < 0)
            return -1;
    } while (next_off);

    return 0;
}
390

391 392
static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
{
393
    RMDemuxContext *rm = s->priv_data;
394 395 396 397 398
    AVStream *st;

    rm->old_format = 1;
    st = av_new_stream(s, 0);
    if (!st)
399
        return -1;
400 401
    st->priv_data = ff_rm_alloc_rmstream();
    return rm_read_audio_stream_info(s, s->pb, st, st->priv_data, 1);
402 403
}

Fabrice Bellard's avatar
Fabrice Bellard committed
404 405
static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
406
    RMDemuxContext *rm = s->priv_data;
Fabrice Bellard's avatar
Fabrice Bellard committed
407
    AVStream *st;
408
    ByteIOContext *pb = s->pb;
409
    unsigned int tag;
410
    int tag_size;
411
    unsigned int start_time, duration;
412
    unsigned int data_off = 0, indx_off = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
413
    char buf[128];
414
    int flags = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
415

416 417 418 419 420
    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')) {
421
        return AVERROR(EIO);
422
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
423 424 425 426 427

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

Fabrice Bellard's avatar
Fabrice Bellard committed
429 430
    for(;;) {
        if (url_feof(pb))
431
            return -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
432 433 434 435
        tag = get_le32(pb);
        tag_size = get_be32(pb);
        get_be16(pb);
#if 0
436
        printf("tag=%c%c%c%c (%08x) size=%d\n",
Fabrice Bellard's avatar
Fabrice Bellard committed
437 438 439 440 441 442 443
               (tag) & 0xff,
               (tag >> 8) & 0xff,
               (tag >> 16) & 0xff,
               (tag >> 24) & 0xff,
               tag,
               tag_size);
#endif
444
        if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A'))
445
            return -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
446 447 448 449 450 451 452 453 454 455
        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 */
456 457
            indx_off = get_be32(pb); /* index offset */
            data_off = get_be32(pb); /* data offset */
Fabrice Bellard's avatar
Fabrice Bellard committed
458
            get_be16(pb); /* nb streams */
459
            flags = get_be16(pb); /* flags */
Fabrice Bellard's avatar
Fabrice Bellard committed
460 461
            break;
        case MKTAG('C', 'O', 'N', 'T'):
462
            rm_read_metadata(s, 1);
Fabrice Bellard's avatar
Fabrice Bellard committed
463 464
            break;
        case MKTAG('M', 'D', 'P', 'R'):
465
            st = av_new_stream(s, 0);
Fabrice Bellard's avatar
Fabrice Bellard committed
466
            if (!st)
467
                return AVERROR(ENOMEM);
Fabrice Bellard's avatar
Fabrice Bellard committed
468 469
            st->id = get_be16(pb);
            get_be32(pb); /* max bit rate */
470
            st->codec->bit_rate = get_be32(pb); /* bit rate */
Fabrice Bellard's avatar
Fabrice Bellard committed
471 472
            get_be32(pb); /* max packet size */
            get_be32(pb); /* avg packet size */
473
            start_time = get_be32(pb); /* start time */
Fabrice Bellard's avatar
Fabrice Bellard committed
474
            get_be32(pb); /* preroll */
475
            duration = get_be32(pb); /* duration */
476 477
            st->start_time = start_time;
            st->duration = duration;
Fabrice Bellard's avatar
Fabrice Bellard committed
478 479
            get_str8(pb, buf, sizeof(buf)); /* desc */
            get_str8(pb, buf, sizeof(buf)); /* mimetype */
480
            st->codec->codec_type = CODEC_TYPE_DATA;
481 482 483
            st->priv_data = ff_rm_alloc_rmstream();
            if (ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data,
                                          get_be32(pb)) < 0)
484
                return -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
485 486 487 488 489 490 491 492 493 494 495
            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 */
496 497
    if (!rm->nb_packets && (flags & 4))
        rm->nb_packets = 3600 * 25;
Fabrice Bellard's avatar
Fabrice Bellard committed
498
    get_be32(pb); /* next data header */
499 500 501 502 503 504 505 506

    if (!data_off)
        data_off = url_ftell(pb) - 18;
    if (indx_off && url_fseek(pb, indx_off, SEEK_SET) >= 0) {
        rm_read_index(s);
        url_fseek(pb, data_off + 18, SEEK_SET);
    }

Fabrice Bellard's avatar
Fabrice Bellard committed
507 508 509
    return 0;
}

510 511 512 513 514 515
static int get_num(ByteIOContext *pb, int *len)
{
    int n, n1;

    n = get_be16(pb);
    (*len)-=2;
516
    n &= 0x7FFF;
517 518 519 520 521 522 523 524 525
    if (n >= 0x4000) {
        return n - 0x4000;
    } else {
        n1 = get_be16(pb);
        (*len)-=2;
        return (n << 16) | n1;
    }
}

526 527 528
/* multiple of 20 bytes for ra144 (ugly) */
#define RAW_PACKET_SIZE 1000

Michael Niedermayer's avatar
Michael Niedermayer committed
529
static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
530
    RMDemuxContext *rm = s->priv_data;
531
    ByteIOContext *pb = s->pb;
Michael Niedermayer's avatar
Michael Niedermayer committed
532
    AVStream *st;
Michael Niedermayer's avatar
Michael Niedermayer committed
533
    uint32_t state=0xFFFFFFFF;
Michael Niedermayer's avatar
Michael Niedermayer committed
534 535

    while(!url_feof(pb)){
536
        int len, num, res, i;
Michael Niedermayer's avatar
Michael Niedermayer committed
537
        *pos= url_ftell(pb) - 3;
Michael Niedermayer's avatar
Michael Niedermayer committed
538 539 540 541 542 543
        if(rm->remaining_len > 0){
            num= rm->current_stream;
            len= rm->remaining_len;
            *timestamp = AV_NOPTS_VALUE;
            *flags= 0;
        }else{
Michael Niedermayer's avatar
Michael Niedermayer committed
544
            state= (state<<8) + get_byte(pb);
545

Michael Niedermayer's avatar
Michael Niedermayer committed
546
            if(state == MKBETAG('I', 'N', 'D', 'X')){
547 548 549 550 551 552 553 554 555 556 557 558 559
                int n_pkts, expected_len;
                len = get_be32(pb);
                url_fskip(pb, 2);
                n_pkts = get_be32(pb);
                expected_len = 20 + n_pkts * 14;
                if (len == 20)
                    /* some files don't add index entries to chunk size... */
                    len = expected_len;
                else if (len != expected_len)
                    av_log(s, AV_LOG_WARNING,
                           "Index size %d (%d pkts) is wrong, should be %d.\n",
                           len, n_pkts, expected_len);
                len -= 14; // we already read part of the index header
Michael Niedermayer's avatar
Michael Niedermayer committed
560 561 562 563
                if(len<0)
                    continue;
                goto skip;
            }
564

565
            if(state > (unsigned)0xFFFF || state <= 12)
Michael Niedermayer's avatar
Michael Niedermayer committed
566
                continue;
567
            len=state - 12;
Michael Niedermayer's avatar
Michael Niedermayer committed
568 569
            state= 0xFFFFFFFF;

Michael Niedermayer's avatar
Michael Niedermayer committed
570 571 572 573 574 575 576 577 578 579 580
            num = get_be16(pb);
            *timestamp = get_be32(pb);
            res= get_byte(pb); /* reserved */
            *flags = get_byte(pb); /* flags */
        }
        for(i=0;i<s->nb_streams;i++) {
            st = s->streams[i];
            if (num == st->id)
                break;
        }
        if (i == s->nb_streams) {
Michael Niedermayer's avatar
Michael Niedermayer committed
581
skip:
Michael Niedermayer's avatar
Michael Niedermayer committed
582 583
            /* skip packet if unknown number */
            url_fskip(pb, len);
584
            rm->remaining_len = 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
585 586 587
            continue;
        }
        *stream_index= i;
588

Michael Niedermayer's avatar
Michael Niedermayer committed
589 590 591 592 593
        return len;
    }
    return -1;
}

594
static int rm_assemble_video_frame(AVFormatContext *s, ByteIOContext *pb,
595
                                   RMDemuxContext *rm, RMStream *vst,
596
                                   AVPacket *pkt, int len, int *pseq)
597 598 599 600 601 602
{
    int hdr, seq, pic_num, len2, pos;
    int type;

    hdr = get_byte(pb); len--;
    type = hdr >> 6;
603 604

    if(type != 3){  // not frame as a part of packet
605
        seq = get_byte(pb); len--;
606 607
    }
    if(type != 1){  // not whole frame
608
        len2 = get_num(pb, &len);
609
        pos  = get_num(pb, &len);
610
        pic_num = get_byte(pb); len--;
611 612 613 614 615 616 617 618
    }
    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)
619
            return -1;
620
        rm->remaining_len -= len;
621 622 623 624 625 626 627 628 629 630
        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

631
    *pseq = seq;
632 633 634
    if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){
        vst->slices = ((hdr & 0x3F) << 1) + 1;
        vst->videobufsize = len2 + 8*vst->slices + 1;
635 636
        av_free_packet(&vst->pkt); //FIXME this should be output.
        if(av_new_packet(&vst->pkt, vst->videobufsize) < 0)
637
            return AVERROR(ENOMEM);
638 639 640 641
        vst->videobufpos = 8*vst->slices + 1;
        vst->cur_slice = 0;
        vst->curpic_num = pic_num;
        vst->pktpos = url_ftell(pb);
642
    }
Roberto Togni's avatar
Roberto Togni committed
643
    if(type == 2)
644 645
        len = FFMIN(len, pos);

646
    if(++vst->cur_slice > vst->slices)
647
        return 1;
648 649
    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);
650
    if(vst->videobufpos + len > vst->videobufsize)
651
        return 1;
652
    if (get_buffer(pb, vst->pkt.data + vst->videobufpos, len) != len)
653
        return AVERROR(EIO);
654
    vst->videobufpos += len;
655 656
    rm->remaining_len-= len;

657
    if(type == 2 || (vst->videobufpos) == vst->videobufsize){
658 659
        vst->pkt.data[0] = vst->cur_slice-1;
        *pkt= vst->pkt;
660
        vst->pkt.data= NULL;
661 662
        vst->pkt.size= 0;
        if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin
663
            memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices,
664
                vst->videobufpos - 1 - 8*vst->slices);
665
        pkt->size = vst->videobufpos + 8*(vst->cur_slice - vst->slices);
666 667
        pkt->pts = AV_NOPTS_VALUE;
        pkt->pos = vst->pktpos;
668
        vst->slices = 0;
669
        return 0;
670 671 672 673 674
    }

    return 1;
}

675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
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;
        }
    }
}

690 691 692 693
/**
 * Perform 4-bit block reordering for SIPR data.
 * @todo This can be optimized, e.g. use memcpy() if data blocks are aligned
 */
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
static void
rm_reorder_sipr_data (RMStream *ast)
{
    int n, bs = ast->sub_packet_h * ast->audio_framesize * 2 / 96; // nibbles per subpacket

    for (n = 0; n < 38; n++) {
        int j;
        int i = bs * sipr_swaps[n][0];
        int o = bs * sipr_swaps[n][1];
        uint8_t *buf = ast->pkt.data;

        /* swap 4bit-nibbles of block 'i' with 'o' */
        for (j = 0; j < bs; j++, i++, o++) {
            int x = (buf[i >> 1] >> (4 * (i & 1))) & 0xF,
                y = (buf[o >> 1] >> (4 * (o & 1))) & 0xF;

            buf[o >> 1] = (x << (4 * (o & 1))) |
                (buf[o >> 1] & (0xF << (4 * !(o & 1))));
            buf[i >> 1] = (y << (4 * (i & 1))) |
                (buf[i >> 1] & (0xF << (4 * !(i & 1))));
        }
    }
}

718
int
719
ff_rm_parse_packet (AVFormatContext *s, ByteIOContext *pb,
720
                    AVStream *st, RMStream *ast, int len, AVPacket *pkt,
721
                    int *seq, int flags, int64_t timestamp)
722
{
723
    RMDemuxContext *rm = s->priv_data;
724 725 726

    if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
        rm->current_stream= st->id;
727
        if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq))
728 729 730 731
            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) ||
732 733
            (st->codec->codec_id == CODEC_ID_ATRAC3) ||
            (st->codec->codec_id == CODEC_ID_SIPR)) {
734
            int x;
735 736 737 738 739
            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;
740

741
            if (flags & 2)
742
                y = ast->sub_packet_cnt = 0;
743
            if (!y)
744
                ast->audiotimestamp = timestamp;
745 746 747 748

            switch(st->codec->codec_id) {
                case CODEC_ID_RA_288:
                    for (x = 0; x < h/2; x++)
749
                        get_buffer(pb, ast->pkt.data+x*2*w+y*cfs, cfs);
750 751 752 753
                    break;
                case CODEC_ID_ATRAC3:
                case CODEC_ID_COOK:
                    for (x = 0; x < w/sps; x++)
754
                        get_buffer(pb, ast->pkt.data+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
755
                    break;
756 757 758
                case CODEC_ID_SIPR:
                    get_buffer(pb, ast->pkt.data + y * w, w);
                    break;
759 760
            }

761
            if (++(ast->sub_packet_cnt) < h)
762
                return -1;
763 764 765
            if (st->codec->codec_id == CODEC_ID_SIPR)
                rm_reorder_sipr_data(ast);

766 767 768
             ast->sub_packet_cnt = 0;
             rm->audio_stream_num = st->index;
             rm->audio_pkt_cnt = h * w / st->codec->block_align;
769 770 771
        } else if (st->codec->codec_id == CODEC_ID_AAC) {
            int x;
            rm->audio_stream_num = st->index;
772 773 774 775
            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);
776
                rm->audio_pkt_cnt = ast->sub_packet_cnt;
777
                ast->audiotimestamp = timestamp;
778 779
            } else
                return -1;
780
        } else {
781
            av_get_packet(pb, pkt, len);
782
            rm_ac3_swap_bytes(st, pkt);
783
        }
784 785 786 787 788 789 790 791 792
    } 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);
793
            av_log(s, AV_LOG_DEBUG, "%d %"PRId64" %d\n", *timestamp, *timestamp*512LL/25, seq);
794

795 796 797
            seq |= (timestamp&~0x3FFF);
            if(seq - timestamp >  0x2000) seq -= 0x4000;
            if(seq - timestamp < -0x2000) seq += 0x4000;
798 799 800 801
        }
    }
#endif

802 803
    pkt->pts= timestamp;
    if (flags & 2)
804 805
        pkt->flags |= PKT_FLAG_KEY;

806
    return st->codec->codec_type == CODEC_TYPE_AUDIO ? rm->audio_pkt_cnt : 0;
807 808
}

809
int
810
ff_rm_retrieve_cache (AVFormatContext *s, ByteIOContext *pb,
811
                      AVStream *st, RMStream *ast, AVPacket *pkt)
812
{
813
    RMDemuxContext *rm = s->priv_data;
814 815 816 817

    assert (rm->audio_pkt_cnt > 0);

    if (st->codec->codec_id == CODEC_ID_AAC)
818
        av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]);
819 820
    else {
        av_new_packet(pkt, st->codec->block_align);
821
        memcpy(pkt->data, ast->pkt.data + st->codec->block_align * //FIXME avoid this
822
               (ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt),
823 824 825
               st->codec->block_align);
    }
    rm->audio_pkt_cnt--;
826 827 828 829
    if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) {
        ast->audiotimestamp = AV_NOPTS_VALUE;
        pkt->flags = PKT_FLAG_KEY;
    } else
Ronald S. Bultje's avatar
Ronald S. Bultje committed
830
        pkt->flags = 0;
831
    pkt->stream_index = st->index;
832 833

    return rm->audio_pkt_cnt;
834 835
}

Fabrice Bellard's avatar
Fabrice Bellard committed
836 837
static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
{
838
    RMDemuxContext *rm = s->priv_data;