~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to extras/ffmpeg/libavformat/asf.c

Tags: upstream-0.7.2.final
ImportĀ upstreamĀ versionĀ 0.7.2.final

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ASF compatible decoder.
 
3
 * Copyright (c) 2000, 2001 Fabrice Bellard.
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 */
 
19
#include "avformat.h"
 
20
#include "avi.h"
 
21
#include "mpegaudio.h"
 
22
#include "asf.h"
 
23
 
 
24
#undef NDEBUG
 
25
#include <assert.h>
 
26
 
 
27
#define FRAME_HEADER_SIZE 17
 
28
// Fix Me! FRAME_HEADER_SIZE may be different. 
 
29
 
 
30
static const GUID index_guid = {
 
31
    0x33000890, 0xe5b1, 0x11cf, { 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb },
 
32
};
 
33
 
 
34
/**********************************/
 
35
/* decoding */
 
36
 
 
37
//#define DEBUG
 
38
 
 
39
#ifdef DEBUG
 
40
#define PRINT_IF_GUID(g,cmp) \
 
41
if (!memcmp(g, &cmp, sizeof(GUID))) \
 
42
    printf("(GUID: %s) ", #cmp)
 
43
 
 
44
static void print_guid(const GUID *g)
 
45
{
 
46
    int i;
 
47
    PRINT_IF_GUID(g, asf_header);
 
48
    else PRINT_IF_GUID(g, file_header);
 
49
    else PRINT_IF_GUID(g, stream_header);
 
50
    else PRINT_IF_GUID(g, audio_stream);
 
51
    else PRINT_IF_GUID(g, audio_conceal_none);
 
52
    else PRINT_IF_GUID(g, video_stream);
 
53
    else PRINT_IF_GUID(g, video_conceal_none);
 
54
    else PRINT_IF_GUID(g, comment_header);
 
55
    else PRINT_IF_GUID(g, codec_comment_header);
 
56
    else PRINT_IF_GUID(g, codec_comment1_header);
 
57
    else PRINT_IF_GUID(g, data_header);
 
58
    else PRINT_IF_GUID(g, index_guid);
 
59
    else PRINT_IF_GUID(g, head1_guid);
 
60
    else PRINT_IF_GUID(g, head2_guid);
 
61
    else PRINT_IF_GUID(g, my_guid);
 
62
    else
 
63
        printf("(GUID: unknown) ");
 
64
    printf("0x%08x, 0x%04x, 0x%04x, {", g->v1, g->v2, g->v3);
 
65
    for(i=0;i<8;i++)
 
66
        printf(" 0x%02x,", g->v4[i]);
 
67
    printf("}\n");
 
68
}
 
69
#undef PRINT_IF_GUID(g,cmp)
 
70
#endif
 
71
 
 
72
static void get_guid(ByteIOContext *s, GUID *g)
 
73
{
 
74
    int i;
 
75
 
 
76
    g->v1 = get_le32(s);
 
77
    g->v2 = get_le16(s);
 
78
    g->v3 = get_le16(s);
 
79
    for(i=0;i<8;i++)
 
80
        g->v4[i] = get_byte(s);
 
81
}
 
82
 
 
83
#if 0
 
84
static void get_str16(ByteIOContext *pb, char *buf, int buf_size)
 
85
{
 
86
    int len, c;
 
87
    char *q;
 
88
 
 
89
    len = get_le16(pb);
 
90
    q = buf;
 
91
    while (len > 0) {
 
92
        c = get_le16(pb);
 
93
        if ((q - buf) < buf_size - 1)
 
94
            *q++ = c;
 
95
        len--;
 
96
    }
 
97
    *q = '\0';
 
98
}
 
99
#endif
 
100
 
 
101
static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
 
102
{
 
103
    int c;
 
104
    char *q;
 
105
 
 
106
    q = buf;
 
107
    while (len > 0) {
 
108
        c = get_le16(pb);
 
109
        if ((q - buf) < buf_size - 1)
 
110
            *q++ = c;
 
111
        len-=2;
 
112
    }
 
113
    *q = '\0';
 
114
}
 
115
 
 
116
static int asf_probe(AVProbeData *pd)
 
117
{
 
118
    GUID g;
 
119
    const unsigned char *p;
 
120
    int i;
 
121
 
 
122
    /* check file header */
 
123
    if (pd->buf_size <= 32)
 
124
        return 0;
 
125
    p = pd->buf;
 
126
    g.v1 = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
 
127
    p += 4;
 
128
    g.v2 = p[0] | (p[1] << 8);
 
129
    p += 2;
 
130
    g.v3 = p[0] | (p[1] << 8);
 
131
    p += 2;
 
132
    for(i=0;i<8;i++)
 
133
        g.v4[i] = *p++;
 
134
 
 
135
    if (!memcmp(&g, &asf_header, sizeof(GUID)))
 
136
        return AVPROBE_SCORE_MAX;
 
137
    else
 
138
        return 0;
 
139
}
 
140
 
 
141
static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 
142
{
 
143
    ASFContext *asf = s->priv_data;
 
144
    GUID g;
 
145
    ByteIOContext *pb = &s->pb;
 
146
    AVStream *st;
 
147
    ASFStream *asf_st;
 
148
    int size, i;
 
149
    int64_t gsize;
 
150
 
 
151
    av_set_pts_info(s, 32, 1, 1000); /* 32 bit pts in ms */
 
152
 
 
153
    get_guid(pb, &g);
 
154
    if (memcmp(&g, &asf_header, sizeof(GUID)))
 
155
        goto fail;
 
156
    get_le64(pb);
 
157
    get_le32(pb);
 
158
    get_byte(pb);
 
159
    get_byte(pb);
 
160
    memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
 
161
    for(;;) {
 
162
        get_guid(pb, &g);
 
163
        gsize = get_le64(pb);
 
164
#ifdef DEBUG
 
165
        printf("%08Lx: ", url_ftell(pb) - 24);
 
166
        print_guid(&g);
 
167
        printf("  size=0x%Lx\n", gsize);
 
168
#endif
 
169
        if (gsize < 24)
 
170
            goto fail;
 
171
        if (!memcmp(&g, &file_header, sizeof(GUID))) {
 
172
            get_guid(pb, &asf->hdr.guid);
 
173
            asf->hdr.file_size          = get_le64(pb);
 
174
            asf->hdr.create_time        = get_le64(pb);
 
175
            asf->hdr.packets_count      = get_le64(pb);
 
176
            asf->hdr.play_time          = get_le64(pb);
 
177
            asf->hdr.send_time          = get_le64(pb);
 
178
            asf->hdr.preroll            = get_le32(pb);
 
179
            asf->hdr.ignore             = get_le32(pb);
 
180
            asf->hdr.flags              = get_le32(pb);
 
181
            asf->hdr.min_pktsize        = get_le32(pb);
 
182
            asf->hdr.max_pktsize        = get_le32(pb);
 
183
            asf->hdr.max_bitrate        = get_le32(pb);
 
184
            asf->packet_size = asf->hdr.max_pktsize;
 
185
            asf->nb_packets = asf->hdr.packets_count;
 
186
        } else if (!memcmp(&g, &stream_header, sizeof(GUID))) {
 
187
            int type, total_size, type_specific_size;
 
188
            unsigned int tag1;
 
189
            int64_t pos1, pos2;
 
190
 
 
191
            pos1 = url_ftell(pb);
 
192
 
 
193
            st = av_new_stream(s, 0);
 
194
            if (!st)
 
195
                goto fail;
 
196
            asf_st = av_mallocz(sizeof(ASFStream));
 
197
            if (!asf_st)
 
198
                goto fail;
 
199
            st->priv_data = asf_st;
 
200
            st->start_time = asf->hdr.preroll / (10000000 / AV_TIME_BASE);
 
201
            st->duration = (asf->hdr.send_time - asf->hdr.preroll) / 
 
202
                (10000000 / AV_TIME_BASE);
 
203
            get_guid(pb, &g);
 
204
            if (!memcmp(&g, &audio_stream, sizeof(GUID))) {
 
205
                type = CODEC_TYPE_AUDIO;
 
206
            } else if (!memcmp(&g, &video_stream, sizeof(GUID))) {
 
207
                type = CODEC_TYPE_VIDEO;
 
208
            } else {
 
209
                goto fail;
 
210
            }
 
211
            get_guid(pb, &g);
 
212
            total_size = get_le64(pb);
 
213
            type_specific_size = get_le32(pb);
 
214
            get_le32(pb);
 
215
            st->id = get_le16(pb) & 0x7f; /* stream id */
 
216
            // mapping of asf ID to AV stream ID;
 
217
            asf->asfid2avid[st->id] = s->nb_streams - 1;
 
218
 
 
219
            get_le32(pb);
 
220
            st->codec.codec_type = type;
 
221
            /* 1 fps default (XXX: put 0 fps instead) */
 
222
            st->codec.frame_rate = 1; 
 
223
            st->codec.frame_rate_base = 1;
 
224
            if (type == CODEC_TYPE_AUDIO) {
 
225
                get_wav_header(pb, &st->codec, type_specific_size);
 
226
                st->need_parsing = 1;
 
227
                /* We have to init the frame size at some point .... */
 
228
                pos2 = url_ftell(pb);
 
229
                if (gsize > (pos2 + 8 - pos1 + 24)) {
 
230
                    asf_st->ds_span = get_byte(pb);
 
231
                    asf_st->ds_packet_size = get_le16(pb);
 
232
                    asf_st->ds_chunk_size = get_le16(pb);
 
233
                    asf_st->ds_data_size = get_le16(pb);
 
234
                    asf_st->ds_silence_data = get_byte(pb);
 
235
                }
 
236
                //printf("Descrambling: ps:%d cs:%d ds:%d s:%d  sd:%d\n",
 
237
                //       asf_st->ds_packet_size, asf_st->ds_chunk_size,
 
238
                //       asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data);
 
239
                if (asf_st->ds_span > 1) {
 
240
                    if (!asf_st->ds_chunk_size
 
241
                        || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1))
 
242
                        asf_st->ds_span = 0; // disable descrambling
 
243
                }
 
244
                switch (st->codec.codec_id) {
 
245
                case CODEC_ID_MP3:
 
246
                    st->codec.frame_size = MPA_FRAME_SIZE;
 
247
                    break;
 
248
                case CODEC_ID_PCM_S16LE:
 
249
                case CODEC_ID_PCM_S16BE:
 
250
                case CODEC_ID_PCM_U16LE:
 
251
                case CODEC_ID_PCM_U16BE:
 
252
                case CODEC_ID_PCM_S8:
 
253
                case CODEC_ID_PCM_U8:
 
254
                case CODEC_ID_PCM_ALAW:
 
255
                case CODEC_ID_PCM_MULAW:
 
256
                    st->codec.frame_size = 1;
 
257
                    break;
 
258
                default:
 
259
                    /* This is probably wrong, but it prevents a crash later */
 
260
                    st->codec.frame_size = 1;
 
261
                    break;
 
262
                }
 
263
            } else {
 
264
                get_le32(pb);
 
265
                get_le32(pb);
 
266
                get_byte(pb);
 
267
                size = get_le16(pb); /* size */
 
268
                get_le32(pb); /* size */
 
269
                st->codec.width = get_le32(pb);
 
270
                st->codec.height = get_le32(pb);
 
271
                /* not available for asf */
 
272
                get_le16(pb); /* panes */
 
273
                st->codec.bits_per_sample = get_le16(pb); /* depth */
 
274
                tag1 = get_le32(pb);
 
275
                url_fskip(pb, 20);
 
276
                if (size > 40) {
 
277
                    st->codec.extradata_size = size - 40;
 
278
                    st->codec.extradata = av_mallocz(st->codec.extradata_size);
 
279
                    get_buffer(pb, st->codec.extradata, st->codec.extradata_size);
 
280
                }
 
281
 
 
282
        /* Extract palette from extradata if bpp <= 8 */
 
283
        /* This code assumes that extradata contains only palette */
 
284
        /* This is true for all paletted codecs implemented in ffmpeg */
 
285
        if (st->codec.extradata_size && (st->codec.bits_per_sample <= 8)) {
 
286
            st->codec.palctrl = av_mallocz(sizeof(AVPaletteControl));
 
287
#ifdef WORDS_BIGENDIAN
 
288
            for (i = 0; i < FFMIN(st->codec.extradata_size, AVPALETTE_SIZE)/4; i++)
 
289
                st->codec.palctrl->palette[i] = bswap_32(((uint32_t*)st->codec.extradata)[i]);
 
290
#else
 
291
            memcpy(st->codec.palctrl->palette, st->codec.extradata,
 
292
                   FFMIN(st->codec.extradata_size, AVPALETTE_SIZE));
 
293
#endif
 
294
            st->codec.palctrl->palette_changed = 1;
 
295
        }
 
296
 
 
297
                st->codec.codec_tag = tag1;
 
298
                st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1);
 
299
            }
 
300
            pos2 = url_ftell(pb);
 
301
            url_fskip(pb, gsize - (pos2 - pos1 + 24));
 
302
        } else if (!memcmp(&g, &data_header, sizeof(GUID))) {
 
303
            break;
 
304
        } else if (!memcmp(&g, &comment_header, sizeof(GUID))) {
 
305
            int len1, len2, len3, len4, len5;
 
306
 
 
307
            len1 = get_le16(pb);
 
308
            len2 = get_le16(pb);
 
309
            len3 = get_le16(pb);
 
310
            len4 = get_le16(pb);
 
311
            len5 = get_le16(pb);
 
312
            get_str16_nolen(pb, len1, s->title, sizeof(s->title));
 
313
            get_str16_nolen(pb, len2, s->author, sizeof(s->author));
 
314
            get_str16_nolen(pb, len3, s->copyright, sizeof(s->copyright));
 
315
            get_str16_nolen(pb, len4, s->comment, sizeof(s->comment));
 
316
            url_fskip(pb, len5);
 
317
       } else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) {
 
318
                int desc_count, i;
 
319
 
 
320
                desc_count = get_le16(pb);
 
321
                for(i=0;i<desc_count;i++)
 
322
                {
 
323
                        int name_len,value_type,value_len,value_num = 0;
 
324
                        char *name, *value;
 
325
 
 
326
                        name_len = get_le16(pb);
 
327
                        name = (char *)av_mallocz(name_len);
 
328
                        get_str16_nolen(pb, name_len, name, name_len);
 
329
                        value_type = get_le16(pb);
 
330
                        value_len = get_le16(pb);
 
331
                        if ((value_type == 0) || (value_type == 1)) // unicode or byte
 
332
                        {
 
333
                                value = (char *)av_mallocz(value_len);
 
334
                                get_str16_nolen(pb, value_len, value, value_len);
 
335
                                if (strcmp(name,"WM/AlbumTitle")==0) { strcpy(s->album, value); }
 
336
                                av_free(value);
 
337
                        }
 
338
                        if ((value_type >= 2) || (value_type <= 5)) // boolean or DWORD or QWORD or WORD
 
339
                        {
 
340
                                if (value_type==2) value_num = get_le32(pb);
 
341
                                if (value_type==3) value_num = get_le32(pb);
 
342
                                if (value_type==4) value_num = get_le64(pb);
 
343
                                if (value_type==5) value_num = get_le16(pb);
 
344
                                if (strcmp(name,"WM/Track")==0) s->track = value_num + 1;
 
345
                                if (strcmp(name,"WM/TrackNumber")==0) s->track = value_num;
 
346
                        }
 
347
                        av_free(name);
 
348
                }
 
349
#if 0
 
350
        } else if (!memcmp(&g, &head1_guid, sizeof(GUID))) {
 
351
            int v1, v2;
 
352
            get_guid(pb, &g);
 
353
            v1 = get_le32(pb);
 
354
            v2 = get_le16(pb);
 
355
        } else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) {
 
356
            int len, v1, n, num;
 
357
            char str[256], *q;
 
358
            char tag[16];
 
359
 
 
360
            get_guid(pb, &g);
 
361
            print_guid(&g);
 
362
 
 
363
            n = get_le32(pb);
 
364
            for(i=0;i<n;i++) {
 
365
                num = get_le16(pb); /* stream number */
 
366
                get_str16(pb, str, sizeof(str));
 
367
                get_str16(pb, str, sizeof(str));
 
368
                len = get_le16(pb);
 
369
                q = tag;
 
370
                while (len > 0) {
 
371
                    v1 = get_byte(pb);
 
372
                    if ((q - tag) < sizeof(tag) - 1)
 
373
                        *q++ = v1;
 
374
                    len--;
 
375
                }
 
376
                *q = '\0';
 
377
            }
 
378
#endif
 
379
        } else if (url_feof(pb)) {
 
380
            goto fail;
 
381
        } else {
 
382
            url_fseek(pb, gsize - 24, SEEK_CUR);
 
383
        }
 
384
    }
 
385
    get_guid(pb, &g);
 
386
    get_le64(pb);
 
387
    get_byte(pb);
 
388
    get_byte(pb);
 
389
    if (url_feof(pb))
 
390
        goto fail;
 
391
    asf->data_offset = url_ftell(pb);
 
392
    asf->packet_size_left = 0;
 
393
 
 
394
    return 0;
 
395
 
 
396
 fail:
 
397
     for(i=0;i<s->nb_streams;i++) {
 
398
        AVStream *st = s->streams[i];
 
399
        if (st) {
 
400
            av_free(st->priv_data);
 
401
            av_free(st->codec.extradata);
 
402
        }
 
403
        av_free(st);
 
404
    }
 
405
    return -1;
 
406
}
 
407
 
 
408
#define DO_2BITS(bits, var, defval) \
 
409
    switch (bits & 3) \
 
410
    { \
 
411
    case 3: var = get_le32(pb); rsize += 4; break; \
 
412
    case 2: var = get_le16(pb); rsize += 2; break; \
 
413
    case 1: var = get_byte(pb); rsize++; break; \
 
414
    default: var = defval; break; \
 
415
    }
 
416
 
 
417
static int asf_get_packet(AVFormatContext *s)
 
418
{
 
419
    ASFContext *asf = s->priv_data;
 
420
    ByteIOContext *pb = &s->pb;
 
421
    uint32_t packet_length, padsize;
 
422
    int rsize = 9;
 
423
    int c;
 
424
    
 
425
    if((url_ftell(&s->pb) - s->data_offset) % asf->packet_size)
 
426
        return -1;
 
427
    assert((url_ftell(&s->pb) - s->data_offset) % asf->packet_size == 0);
 
428
    
 
429
    c = get_byte(pb);
 
430
    if (c != 0x82) {
 
431
        if (!url_feof(pb))
 
432
            av_log(s, AV_LOG_ERROR, "ff asf bad header %x  at:%lld\n", c, url_ftell(pb));
 
433
    }
 
434
    if ((c & 0x0f) == 2) { // always true for now
 
435
        if (get_le16(pb) != 0) {
 
436
            if (!url_feof(pb))
 
437
                av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n");
 
438
            return -EIO;
 
439
        }
 
440
        rsize+=2;
 
441
/*    }else{
 
442
        if (!url_feof(pb))
 
443
            printf("ff asf bad header %x  at:%lld\n", c, url_ftell(pb));
 
444
        return -EIO;*/
 
445
    }
 
446
 
 
447
    asf->packet_flags = get_byte(pb);
 
448
    asf->packet_property = get_byte(pb);
 
449
 
 
450
    DO_2BITS(asf->packet_flags >> 5, packet_length, asf->packet_size);
 
451
    DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored
 
452
    DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length
 
453
 
 
454
    asf->packet_timestamp = get_le32(pb);
 
455
    get_le16(pb); /* duration */
 
456
    // rsize has at least 11 bytes which have to be present
 
457
 
 
458
    if (asf->packet_flags & 0x01) {
 
459
        asf->packet_segsizetype = get_byte(pb); rsize++;
 
460
        asf->packet_segments = asf->packet_segsizetype & 0x3f;
 
461
    } else {
 
462
        asf->packet_segments = 1;
 
463
        asf->packet_segsizetype = 0x80;
 
464
    }
 
465
    asf->packet_size_left = packet_length - padsize - rsize;
 
466
    if (packet_length < asf->hdr.min_pktsize)
 
467
        padsize += asf->hdr.min_pktsize - packet_length;
 
468
    asf->packet_padsize = padsize;
 
469
#ifdef DEBUG
 
470
    printf("packet: size=%d padsize=%d  left=%d\n", asf->packet_size, asf->packet_padsize, asf->packet_size_left);
 
471
#endif
 
472
    return 0;
 
473
}
 
474
 
 
475
static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
 
476
{
 
477
    ASFContext *asf = s->priv_data;
 
478
    ASFStream *asf_st = 0;
 
479
    ByteIOContext *pb = &s->pb;
 
480
    //static int pc = 0;
 
481
    for (;;) {
 
482
        int rsize = 0;
 
483
        if (asf->packet_size_left < FRAME_HEADER_SIZE
 
484
            || asf->packet_segments < 1) {
 
485
            //asf->packet_size_left <= asf->packet_padsize) {
 
486
            int ret = asf->packet_size_left + asf->packet_padsize;
 
487
            //printf("PacketLeftSize:%d  Pad:%d Pos:%Ld\n", asf->packet_size_left, asf->packet_padsize, url_ftell(pb));
 
488
            /* fail safe */
 
489
            url_fskip(pb, ret);
 
490
            asf->packet_pos= url_ftell(&s->pb);
 
491
            ret = asf_get_packet(s);
 
492
            //printf("READ ASF PACKET  %d   r:%d   c:%d\n", ret, asf->packet_size_left, pc++);
 
493
            if (ret < 0 || url_feof(pb))
 
494
                return -EIO;
 
495
            asf->packet_time_start = 0;
 
496
            continue;
 
497
        }
 
498
        if (asf->packet_time_start == 0) {
 
499
            /* read frame header */
 
500
            int num = get_byte(pb);
 
501
            asf->packet_segments--;
 
502
            rsize++;
 
503
            asf->packet_key_frame = (num & 0x80) >> 7;
 
504
            asf->stream_index = asf->asfid2avid[num & 0x7f];
 
505
            // sequence should be ignored!
 
506
            DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
 
507
            DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
 
508
            DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
 
509
//printf("key:%d stream:%d seq:%d offset:%d replic_size:%d\n", asf->packet_key_frame, asf->stream_index, asf->packet_seq, //asf->packet_frag_offset, asf->packet_replic_size);
 
510
            if (asf->packet_replic_size > 1) {
 
511
                assert(asf->packet_replic_size >= 8);
 
512
                // it should be always at least 8 bytes - FIXME validate
 
513
                asf->packet_obj_size = get_le32(pb);
 
514
                asf->packet_frag_timestamp = get_le32(pb); // timestamp
 
515
                if (asf->packet_replic_size > 8)
 
516
                    url_fskip(pb, asf->packet_replic_size - 8);
 
517
                rsize += asf->packet_replic_size; // FIXME - check validity
 
518
            } else if (asf->packet_replic_size==1){
 
519
                // multipacket - frag_offset is begining timestamp
 
520
                asf->packet_time_start = asf->packet_frag_offset;
 
521
                asf->packet_frag_offset = 0;
 
522
                asf->packet_frag_timestamp = asf->packet_timestamp;
 
523
 
 
524
                asf->packet_time_delta = get_byte(pb);
 
525
                rsize++;
 
526
            }else{
 
527
                assert(asf->packet_replic_size==0);
 
528
            }
 
529
            if (asf->packet_flags & 0x01) {
 
530
                DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
 
531
#undef DO_2BITS
 
532
                //printf("Fragsize %d\n", asf->packet_frag_size);
 
533
            } else {
 
534
                asf->packet_frag_size = asf->packet_size_left - rsize;
 
535
                //printf("Using rest  %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize);
 
536
            }
 
537
            if (asf->packet_replic_size == 1) {
 
538
                asf->packet_multi_size = asf->packet_frag_size;
 
539
                if (asf->packet_multi_size > asf->packet_size_left) {
 
540
                    asf->packet_segments = 0;
 
541
                    continue;
 
542
                }
 
543
            }
 
544
            asf->packet_size_left -= rsize;
 
545
            //printf("___objsize____  %d   %d    rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize);
 
546
 
 
547
            if (asf->stream_index < 0) {
 
548
                asf->packet_time_start = 0;
 
549
                /* unhandled packet (should not happen) */
 
550
                url_fskip(pb, asf->packet_frag_size);
 
551
                asf->packet_size_left -= asf->packet_frag_size;
 
552
                av_log(s, AV_LOG_ERROR, "ff asf skip %d  %d\n", asf->packet_frag_size, num & 0x7f);
 
553
                continue;
 
554
            }
 
555
            asf->asf_st = s->streams[asf->stream_index]->priv_data;
 
556
        }
 
557
        asf_st = asf->asf_st;
 
558
 
 
559
        if ((asf->packet_frag_offset != asf_st->frag_offset
 
560
             || (asf->packet_frag_offset
 
561
                 && asf->packet_seq != asf_st->seq)) // seq should be ignored
 
562
           ) {
 
563
            /* cannot continue current packet: free it */
 
564
            // FIXME better check if packet was already allocated
 
565
            av_log(s, AV_LOG_INFO, "ff asf parser skips: %d - %d     o:%d - %d    %d %d   fl:%d\n",
 
566
                   asf_st->pkt.size,
 
567
                   asf->packet_obj_size,
 
568
                   asf->packet_frag_offset, asf_st->frag_offset,
 
569
                   asf->packet_seq, asf_st->seq, asf->packet_frag_size);
 
570
            if (asf_st->pkt.size)
 
571
                av_free_packet(&asf_st->pkt);
 
572
            asf_st->frag_offset = 0;
 
573
            if (asf->packet_frag_offset != 0) {
 
574
                url_fskip(pb, asf->packet_frag_size);
 
575
                av_log(s, AV_LOG_INFO, "ff asf parser skiping %db\n", asf->packet_frag_size);
 
576
                asf->packet_size_left -= asf->packet_frag_size;
 
577
                continue;
 
578
            }
 
579
        }
 
580
        if (asf->packet_replic_size == 1) {
 
581
            // frag_offset is here used as the begining timestamp
 
582
            asf->packet_frag_timestamp = asf->packet_time_start;
 
583
            asf->packet_time_start += asf->packet_time_delta;
 
584
            asf->packet_obj_size = asf->packet_frag_size = get_byte(pb);
 
585
            asf->packet_size_left--;
 
586
            asf->packet_multi_size--;
 
587
            if (asf->packet_multi_size < asf->packet_obj_size)
 
588
            {
 
589
                asf->packet_time_start = 0;
 
590
                url_fskip(pb, asf->packet_multi_size);
 
591
                asf->packet_size_left -= asf->packet_multi_size;
 
592
                continue;
 
593
            }
 
594
            asf->packet_multi_size -= asf->packet_obj_size;
 
595
            //printf("COMPRESS size  %d  %d  %d   ms:%d\n", asf->packet_obj_size, asf->packet_frag_timestamp, asf->packet_size_left, asf->packet_multi_size);
 
596
        }
 
597
        if (asf_st->frag_offset == 0) {
 
598
            /* new packet */
 
599
            av_new_packet(&asf_st->pkt, asf->packet_obj_size);
 
600
            asf_st->seq = asf->packet_seq;
 
601
            asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll;
 
602
            asf_st->pkt.stream_index = asf->stream_index;
 
603
            asf_st->packet_pos= asf->packet_pos;            
 
604
//printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n", 
 
605
//asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & PKT_FLAG_KEY,
 
606
//s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO, asf->packet_obj_size);
 
607
            if (s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO) 
 
608
                asf->packet_key_frame = 1;
 
609
            if (asf->packet_key_frame)
 
610
                asf_st->pkt.flags |= PKT_FLAG_KEY;
 
611
        }
 
612
 
 
613
        /* read data */
 
614
        //printf("READ PACKET s:%d  os:%d  o:%d,%d  l:%d   DATA:%p\n",
 
615
        //       asf->packet_size, asf_st->pkt.size, asf->packet_frag_offset,
 
616
        //       asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data);
 
617
        asf->packet_size_left -= asf->packet_frag_size;
 
618
        if (asf->packet_size_left < 0)
 
619
            continue;
 
620
        get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset,
 
621
                   asf->packet_frag_size);
 
622
        asf_st->frag_offset += asf->packet_frag_size;
 
623
        /* test if whole packet is read */
 
624
        if (asf_st->frag_offset == asf_st->pkt.size) {
 
625
            /* return packet */
 
626
            if (asf_st->ds_span > 1) {
 
627
                /* packet descrambling */
 
628
                char* newdata = av_malloc(asf_st->pkt.size);
 
629
                if (newdata) {
 
630
                    int offset = 0;
 
631
                    while (offset < asf_st->pkt.size) {
 
632
                        int off = offset / asf_st->ds_chunk_size;
 
633
                        int row = off / asf_st->ds_span;
 
634
                        int col = off % asf_st->ds_span;
 
635
                        int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size;
 
636
                        //printf("off:%d  row:%d  col:%d  idx:%d\n", off, row, col, idx);
 
637
                        memcpy(newdata + offset,
 
638
                               asf_st->pkt.data + idx * asf_st->ds_chunk_size,
 
639
                               asf_st->ds_chunk_size);
 
640
                        offset += asf_st->ds_chunk_size;
 
641
                    }
 
642
                    av_free(asf_st->pkt.data);
 
643
                    asf_st->pkt.data = newdata;
 
644
                }
 
645
            }
 
646
            asf_st->frag_offset = 0;
 
647
            memcpy(pkt, &asf_st->pkt, sizeof(AVPacket));
 
648
            //printf("packet %d %d\n", asf_st->pkt.size, asf->packet_frag_size);
 
649
            asf_st->pkt.size = 0;
 
650
            asf_st->pkt.data = 0;
 
651
            break; // packet completed
 
652
        }
 
653
    }
 
654
    return 0;
 
655
}
 
656
 
 
657
static int asf_read_close(AVFormatContext *s)
 
658
{
 
659
    int i;
 
660
 
 
661
    for(i=0;i<s->nb_streams;i++) {
 
662
        AVStream *st = s->streams[i];
 
663
        av_free(st->priv_data);
 
664
        av_free(st->codec.extradata);
 
665
    av_free(st->codec.palctrl);
 
666
    }
 
667
    return 0;
 
668
}
 
669
 
 
670
// Added to support seeking after packets have been read
 
671
// If information is not reset, read_packet fails due to
 
672
// leftover information from previous reads
 
673
static void asf_reset_header(AVFormatContext *s)
 
674
{
 
675
    ASFContext *asf = s->priv_data;
 
676
    ASFStream *asf_st;
 
677
    int i;
 
678
 
 
679
    asf->packet_nb_frames = 0;
 
680
    asf->packet_timestamp_start = -1;
 
681
    asf->packet_timestamp_end = -1;
 
682
    asf->packet_size_left = 0;
 
683
    asf->packet_segments = 0;
 
684
    asf->packet_flags = 0;
 
685
    asf->packet_property = 0;
 
686
    asf->packet_timestamp = 0;
 
687
    asf->packet_segsizetype = 0;
 
688
    asf->packet_segments = 0;
 
689
    asf->packet_seq = 0;
 
690
    asf->packet_replic_size = 0;
 
691
    asf->packet_key_frame = 0;
 
692
    asf->packet_padsize = 0;
 
693
    asf->packet_frag_offset = 0;
 
694
    asf->packet_frag_size = 0;
 
695
    asf->packet_frag_timestamp = 0;
 
696
    asf->packet_multi_size = 0;
 
697
    asf->packet_obj_size = 0;
 
698
    asf->packet_time_delta = 0;
 
699
    asf->packet_time_start = 0;
 
700
    
 
701
    for(i=0; i<s->nb_streams; i++){
 
702
        asf_st= s->streams[i]->priv_data;
 
703
        av_free_packet(&asf_st->pkt);
 
704
        asf_st->frag_offset=0;
 
705
        asf_st->seq=0;
 
706
    }
 
707
    asf->asf_st= NULL;
 
708
}
 
709
 
 
710
static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit)
 
711
{
 
712
    ASFContext *asf = s->priv_data;
 
713
    AVPacket pkt1, *pkt = &pkt1;
 
714
    ASFStream *asf_st;
 
715
    int64_t pts;
 
716
    int64_t pos= *ppos;
 
717
    int i;
 
718
    int64_t start_pos[s->nb_streams];
 
719
    
 
720
    for(i=0; i<s->nb_streams; i++){
 
721
        start_pos[i]= pos;
 
722
    }
 
723
    
 
724
    pos= (pos+asf->packet_size-1-s->data_offset)/asf->packet_size*asf->packet_size+ s->data_offset;
 
725
    *ppos= pos;
 
726
    url_fseek(&s->pb, pos, SEEK_SET);
 
727
    
 
728
//printf("asf_read_pts\n");
 
729
    asf_reset_header(s);
 
730
    for(;;){
 
731
        if (av_read_frame(s, pkt) < 0){
 
732
            av_log(s, AV_LOG_INFO, "seek failed\n");
 
733
            return AV_NOPTS_VALUE;
 
734
        }
 
735
        
 
736
        pts= pkt->pts;
 
737
 
 
738
        av_free_packet(pkt);
 
739
        if(pkt->flags&PKT_FLAG_KEY){
 
740
            i= pkt->stream_index;
 
741
 
 
742
            asf_st= s->streams[i]->priv_data;
 
743
 
 
744
            assert((asf_st->packet_pos - s->data_offset) % asf->packet_size == 0);
 
745
            pos= asf_st->packet_pos;
 
746
 
 
747
            av_add_index_entry(s->streams[i], pos, pts, pos - start_pos[i] + 1, AVINDEX_KEYFRAME);
 
748
            start_pos[i]= asf_st->packet_pos + 1;
 
749
            
 
750
            if(pkt->stream_index == stream_index)
 
751
               break;
 
752
        }
 
753
    }
 
754
 
 
755
    *ppos= pos;
 
756
//printf("found keyframe at %Ld stream %d stamp:%Ld\n", *ppos, stream_index, pts);
 
757
 
 
758
    return pts;
 
759
}
 
760
 
 
761
static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts)
 
762
{
 
763
    ASFContext *asf = s->priv_data;
 
764
    
 
765
    if (asf->packet_size <= 0)
 
766
        return -1;
 
767
 
 
768
    if(av_seek_frame_binary(s, stream_index, pts)<0)
 
769
        return -1;
 
770
 
 
771
    asf_reset_header(s);
 
772
    return 0;
 
773
}
 
774
 
 
775
static AVInputFormat asf_iformat = {
 
776
    "asf",
 
777
    "asf format",
 
778
    sizeof(ASFContext),
 
779
    asf_probe,
 
780
    asf_read_header,
 
781
    asf_read_packet,
 
782
    asf_read_close,
 
783
    asf_read_seek,
 
784
    asf_read_pts,
 
785
};
 
786
 
 
787
#ifdef CONFIG_ENCODERS
 
788
    extern AVOutputFormat asf_oformat;
 
789
    extern AVOutputFormat asf_stream_oformat;
 
790
#endif //CONFIG_ENCODERS
 
791
 
 
792
int asf_init(void)
 
793
{
 
794
    av_register_input_format(&asf_iformat);
 
795
#ifdef CONFIG_ENCODERS
 
796
    av_register_output_format(&asf_oformat);
 
797
    av_register_output_format(&asf_stream_oformat);
 
798
#endif //CONFIG_ENCODERS
 
799
    return 0;
 
800
}