Coverage Report

Created: 2025-11-11 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/asf/asfpacket.c
Line
Count
Source
1
/*****************************************************************************
2
 * asfpacket.c :
3
 *****************************************************************************
4
 * Copyright © 2001-2004, 2011, 2014 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
#ifdef HAVE_CONFIG_H
23
# include "config.h"
24
#endif
25
26
#include "asfpacket.h"
27
#include <limits.h>
28
29
#ifndef NDEBUG
30
# define ASF_DEBUG 1
31
#endif
32
33
typedef struct asf_packet_t
34
{
35
    uint32_t property;
36
    uint32_t length;
37
    uint32_t padding_length;
38
    vlc_tick_t  send_time;
39
    bool multiple;
40
    int length_type;
41
42
    /* buffer handling for this ASF packet */
43
    uint32_t i_skip;
44
    const uint8_t *p_peek;
45
    uint32_t left;
46
} asf_packet_t;
47
48
static inline int GetValue2b(uint32_t *var, const uint8_t *p, unsigned int *skip, int left, int bits)
49
305k
{
50
305k
    switch(bits&0x03)
51
305k
    {
52
100k
    case 1:
53
100k
        if (left < 1)
54
30
            return -1;
55
100k
        *var = p[*skip]; *skip += 1;
56
100k
        return 0;
57
31.6k
    case 2:
58
31.6k
        if (left < 2)
59
45
            return -1;
60
31.5k
        *var = GetWLE(&p[*skip]); *skip += 2;
61
31.5k
        return 0;
62
51.7k
    case 3:
63
51.7k
        if (left < 4)
64
97
            return -1;
65
51.6k
        *var = GetDWLE(&p[*skip]); *skip += 4;
66
51.6k
        return 0;
67
121k
    case 0:
68
121k
    default:
69
121k
        return 0;
70
305k
    }
71
305k
}
72
73
static int DemuxSubPayload( asf_packet_sys_t *p_packetsys,
74
                            uint8_t i_stream_number, asf_track_info_t *p_tkinfo,
75
                            uint32_t i_sub_payload_data_length, vlc_tick_t i_pts, vlc_tick_t i_dts,
76
                            uint32_t i_media_object_number, uint32_t i_media_object_offset,
77
                            bool b_keyframe, bool b_ignore_pts )
78
200k
{
79
200k
    block_t **pp_frame = &p_tkinfo->p_frame;
80
81
200k
    if( p_packetsys->b_deduplicate )
82
0
    {
83
0
        for(size_t i=0; i<p_tkinfo->i_pktcount; i++)
84
0
        {
85
0
            if(p_tkinfo->prev[i].media_number == i_media_object_number &&
86
0
               p_tkinfo->prev[i].media_offset == i_media_object_offset)
87
0
            {
88
0
                vlc_debug(p_packetsys->logger, "dropping duplicate num %"PRIu32" off %"PRIu32,
89
0
                          i_media_object_number , i_media_object_offset);
90
0
                return vlc_stream_Read( p_packetsys->s, NULL, i_sub_payload_data_length ) != i_sub_payload_data_length ? -1 : 0;
91
0
            }
92
0
        }
93
94
0
        unsigned dedupindex;
95
0
        if( p_tkinfo->i_pktcount < ASFPACKET_DEDUPLICATE )
96
0
            dedupindex = p_tkinfo->i_pkt = p_tkinfo->i_pktcount++;
97
0
        else
98
0
            dedupindex = (++p_tkinfo->i_pkt) % ASFPACKET_DEDUPLICATE;
99
100
0
        p_tkinfo->prev[dedupindex].media_number = i_media_object_number;
101
0
        p_tkinfo->prev[dedupindex].media_offset = i_media_object_offset;
102
0
    }
103
104
    /* FIXME I don't use i_media_object_number, sould I ? */
105
200k
    if( *pp_frame && i_media_object_offset == 0 )
106
195k
    {
107
195k
        p_packetsys->pf_send( p_packetsys, i_stream_number, pp_frame );
108
195k
    }
109
110
200k
    block_t *p_frag = vlc_stream_Block( p_packetsys->s, i_sub_payload_data_length );
111
200k
    if( p_frag == NULL ) {
112
1
        vlc_warning( p_packetsys->logger, "cannot read data" );
113
1
        return -1;
114
1
    }
115
116
200k
    p_frag->i_pts = (b_ignore_pts) ? VLC_TICK_INVALID : VLC_TICK_0 + i_pts;
117
200k
    p_frag->i_dts = VLC_TICK_0 + i_dts;
118
200k
    if ( b_keyframe )
119
3.09k
        p_frag->i_flags |= BLOCK_FLAG_TYPE_I;
120
121
200k
    block_ChainAppend( pp_frame, p_frag );
122
123
200k
    return 0;
124
200k
}
125
126
static void ParsePayloadExtensions( asf_packet_sys_t *p_packetsys,
127
                                    const asf_track_info_t *p_tkinfo,
128
                                    const uint8_t *p_data, size_t i_data,
129
                                    bool *b_keyframe )
130
9.04k
{
131
9.04k
    if ( !p_tkinfo || !p_tkinfo->p_esp || !p_tkinfo->p_esp->p_ext )
132
2.49k
        return;
133
134
6.55k
    uint16_t i_payload_extensions_size;
135
6.55k
    asf_payload_extension_system_t *p_ext = NULL;
136
137
    /* Extensions always come in the declared order */
138
13.1k
    for ( int i=0; i< p_tkinfo->p_esp->i_payload_extension_system_count; i++ )
139
6.88k
    {
140
6.88k
        p_ext = &p_tkinfo->p_esp->p_ext[i];
141
6.88k
        if ( p_ext->i_data_size == 0xFFFF ) /* Variable length extension data */
142
400
        {
143
400
            if ( i_data < 2 ) return;
144
389
            i_payload_extensions_size = GetWLE( p_data );
145
389
            p_data += 2;
146
389
            i_data -= 2;
147
389
            i_payload_extensions_size = 0;
148
389
        }
149
6.48k
        else
150
6.48k
        {
151
6.48k
            i_payload_extensions_size = p_ext->i_data_size;
152
6.48k
        }
153
154
6.87k
        if ( i_data < i_payload_extensions_size ) return;
155
156
6.57k
        if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_outputcleanpoint_guid ) )
157
0
        {
158
0
            if ( i_payload_extensions_size != 1 ) goto sizeerror;
159
0
            *b_keyframe |= *p_data;
160
0
        }
161
6.57k
        else if ( guidcmp( &p_ext->i_extension_id, &asf_dvr_sampleextension_videoframe_guid ) )
162
0
        {
163
0
            if ( i_payload_extensions_size != 4U ) goto sizeerror;
164
165
0
            uint32_t i_val = GetDWLE( p_data );
166
            /* Valid keyframe must be a split frame start fragment */
167
0
            *b_keyframe = i_val & ASF_EXTENSION_VIDEOFRAME_NEWFRAME;
168
0
            if ( *b_keyframe )
169
0
            {
170
                /* And flagged as IFRAME */
171
0
                *b_keyframe |= ( ( i_val & ASF_EXTENSION_VIDEOFRAME_TYPE_MASK )
172
0
                                 == ASF_EXTENSION_VIDEOFRAME_IFRAME );
173
0
            }
174
0
        }
175
6.57k
        else if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_pixelaspectratio_guid ) &&
176
0
                  p_packetsys->pf_setaspectratio )
177
0
        {
178
0
            if ( i_payload_extensions_size != 2U ) goto sizeerror;
179
180
0
            p_packetsys->pf_setaspectratio( p_packetsys, p_tkinfo->p_sp->i_stream_number,
181
0
                                            p_data[0], p_data[1] );
182
0
        }
183
6.57k
        else if ( guidcmp( &p_ext->i_extension_id, &asf_dvr_sampleextension_timing_rep_data_guid ) )
184
0
        {
185
0
            if ( i_payload_extensions_size != 48 ) goto sizeerror;
186
            /* const int64_t i_pts = GetQWLE(&p_data[8]); */
187
0
        }
188
#if 0
189
        else
190
        {
191
            msg_Dbg( p_demux, "Unknown extension " GUID_FMT, GUID_PRINT( p_ext->i_extension_id ) );
192
        }
193
#endif
194
6.57k
        i_data -= i_payload_extensions_size;
195
6.57k
        p_data += i_payload_extensions_size;
196
6.57k
    }
197
198
6.24k
    return;
199
200
6.24k
sizeerror:
201
0
    vlc_warning( p_packetsys->logger, "Unknown extension " GUID_FMT " data size of %u",
202
0
              GUID_PRINT( p_ext->i_extension_id ), i_payload_extensions_size );
203
0
}
204
205
static int DemuxPayload(asf_packet_sys_t *p_packetsys, asf_packet_t *pkt, int i_payload)
206
70.7k
{
207
#ifndef ASF_DEBUG
208
    VLC_UNUSED( i_payload );
209
#endif
210
70.7k
    if( ! pkt->left || pkt->i_skip >= pkt->left )
211
132
        return -1;
212
213
70.7k
    bool b_packet_keyframe = pkt->p_peek[pkt->i_skip] >> 7;
214
70.6k
    uint8_t i_stream_number = pkt->p_peek[pkt->i_skip++] & 0x7f;
215
216
70.6k
    uint32_t i_media_object_number = 0;
217
70.6k
    if (GetValue2b(&i_media_object_number, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 4) < 0)
218
34
        return -1;
219
70.5k
    uint32_t i_media_object_offset = 0;
220
70.5k
    if (GetValue2b(&i_media_object_offset, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 2) < 0)
221
51
        return -1;
222
70.5k
    uint32_t i_replicated_data_length = 0;
223
70.5k
    if (GetValue2b(&i_replicated_data_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property) < 0)
224
61
        return -1;
225
226
70.4k
    vlc_tick_t i_pkt_time;
227
70.4k
    vlc_tick_t i_pkt_time_delta = 0;
228
70.4k
    uint32_t i_payload_data_length = 0;
229
70.4k
    uint32_t i_temp_payload_length = 0;
230
231
    /* First packet, in case we do not have index to guess preroll start time */
232
70.4k
    if ( *p_packetsys->pi_preroll_start == ASFPACKET_PREROLL_FROM_CURRENT )
233
0
        *p_packetsys->pi_preroll_start = pkt->send_time;
234
235
70.4k
    asf_track_info_t *p_tkinfo = p_packetsys->pf_gettrackinfo( p_packetsys, i_stream_number );
236
70.4k
    if ( !p_tkinfo )
237
48.8k
        goto skip;
238
239
70.4k
    bool b_ignore_pts = (p_tkinfo->i_cat == VIDEO_ES); /* ignore PTS delta with video when not set by mux */
240
241
21.6k
    if( pkt->left - pkt->i_skip < i_replicated_data_length )
242
81
        return -1;
243
244
    /* Non compressed */
245
21.5k
    if( i_replicated_data_length > 7 ) // should be at least 8 bytes
246
9.04k
    {
247
        /* Followed by 2 optional DWORDS, offset in media and *media* presentation time */
248
9.04k
        i_pkt_time = VLC_TICK_FROM_MS(GetDWLE( pkt->p_peek + pkt->i_skip + 4 ));
249
250
        /* Parsing extensions, See 7.3.1 */
251
9.04k
        ParsePayloadExtensions( p_packetsys, p_tkinfo,
252
9.04k
                                &pkt->p_peek[pkt->i_skip + 8],
253
9.04k
                                i_replicated_data_length - 8,
254
9.04k
                                &b_packet_keyframe );
255
9.04k
        i_pkt_time -= *p_packetsys->pi_preroll;
256
9.04k
        pkt->i_skip += i_replicated_data_length;
257
9.04k
    }
258
12.5k
    else if ( i_replicated_data_length == 0 )
259
7.76k
    {
260
        /* optional DWORDS missing */
261
7.76k
        i_pkt_time = pkt->send_time;
262
7.76k
    }
263
    /* Compressed payload */
264
4.74k
    else if( i_replicated_data_length == 1 )
265
4.69k
    {
266
        /* i_media_object_offset is *media* presentation time */
267
        /* Next byte is *media* Presentation Time Delta */
268
4.69k
        i_pkt_time_delta = VLC_TICK_FROM_MS(pkt->p_peek[pkt->i_skip]);
269
4.69k
        b_ignore_pts = false;
270
4.69k
        i_pkt_time = VLC_TICK_FROM_MS(i_media_object_offset);
271
4.69k
        i_pkt_time -= *p_packetsys->pi_preroll;
272
4.69k
        pkt->i_skip++;
273
4.69k
        i_media_object_offset = 0;
274
4.69k
    }
275
58
    else
276
58
    {
277
        /* >1 && <8 Invalid replicated length ! */
278
58
        vlc_warning( p_packetsys->logger, "Invalid replicated data length detected." );
279
58
        if( pkt->length - pkt->i_skip < pkt->padding_length )
280
4
            return -1;
281
282
54
        i_payload_data_length = pkt->length - pkt->padding_length - pkt->i_skip;
283
54
        goto skip;
284
58
    }
285
286
21.5k
    if( ! pkt->left || pkt->i_skip >= pkt->left )
287
4
        return -1;
288
289
21.5k
    bool b_preroll_done = ( pkt->send_time > (*p_packetsys->pi_preroll_start + *p_packetsys->pi_preroll) );
290
291
21.4k
    if (i_pkt_time < 0) i_pkt_time = 0; // FIXME?
292
293
21.4k
    if( pkt->multiple ) {
294
13.3k
        if (GetValue2b(&i_temp_payload_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->length_type) < 0)
295
11
            return -1;
296
13.3k
    }
297
8.10k
    else
298
8.10k
    {
299
8.10k
        if( pkt->length - pkt->i_skip < pkt->padding_length )
300
11
            return -1;
301
8.08k
        i_temp_payload_length = pkt->length - pkt->padding_length - pkt->i_skip;
302
8.08k
    }
303
304
21.4k
    i_payload_data_length = i_temp_payload_length;
305
306
21.4k
#ifdef ASF_DEBUG
307
21.4k
     vlc_debug( p_packetsys->logger,
308
21.4k
              "payload(%d) stream_number:%"PRIu8" media_object_number:%d media_object_offset:%"PRIu32
309
21.4k
                " replicated_data_length:%"PRIu32" payload_data_length %"PRIu32,
310
21.4k
              i_payload + 1, i_stream_number, i_media_object_number,
311
21.4k
              i_media_object_offset, i_replicated_data_length, i_payload_data_length );
312
21.4k
     vlc_debug( p_packetsys->logger,
313
21.4k
              "  pkttime=%"PRId64" st=%"PRId64,
314
21.4k
              i_pkt_time, MS_FROM_VLC_TICK(pkt->send_time) );
315
21.4k
#endif
316
317
21.4k
     if( ! i_payload_data_length || i_payload_data_length > pkt->left )
318
1.17k
     {
319
1.17k
         vlc_debug( p_packetsys->logger, "  payload length problem %d %"PRIu32
320
1.17k
                    " %"PRIu32, pkt->multiple, i_payload_data_length, pkt->left );
321
1.17k
         return -1;
322
1.17k
     }
323
324
20.2k
    if ( p_packetsys->pf_doskip &&
325
20.2k
         p_packetsys->pf_doskip( p_packetsys, i_stream_number, b_packet_keyframe ) )
326
1.53k
        goto skip;
327
328
18.7k
    if ( b_preroll_done )
329
5.50k
    {
330
5.50k
        vlc_tick_t i_track_time = i_pkt_time;
331
332
5.50k
        if ( p_packetsys->pf_updatetime )
333
5.50k
            p_packetsys->pf_updatetime( p_packetsys, i_stream_number, i_track_time );
334
5.50k
    }
335
336
18.7k
    if( p_packetsys->pf_updatesendtime )
337
18.7k
        p_packetsys->pf_updatesendtime( p_packetsys, pkt->send_time );
338
339
18.7k
    vlc_tick_t i_subpayload_delta = 0;
340
252k
    while (i_payload_data_length && pkt->i_skip < pkt->left )
341
238k
    {
342
238k
        uint32_t i_sub_payload_data_length = i_payload_data_length;
343
238k
        if( i_replicated_data_length == 1 )
344
224k
        {
345
224k
            i_sub_payload_data_length = pkt->p_peek[pkt->i_skip++];
346
224k
            i_payload_data_length--;
347
224k
            if( i_sub_payload_data_length > i_payload_data_length )
348
4.16k
                goto skip;
349
224k
        }
350
351
234k
        if (pkt->i_skip && vlc_stream_Read( p_packetsys->s, NULL, pkt->i_skip ) != pkt->i_skip )
352
0
        {
353
0
            vlc_warning( p_packetsys->logger, "unexpected end of file" );
354
0
            return -1;
355
0
        }
356
357
234k
        vlc_tick_t i_payload_pts;
358
234k
        i_payload_pts = i_pkt_time + i_subpayload_delta;
359
234k
        if ( p_tkinfo->p_sp )
360
234k
            i_payload_pts -= VLC_TICK_FROM_MSFTIME(p_tkinfo->p_sp->i_time_offset);
361
362
234k
        vlc_tick_t i_payload_dts = i_pkt_time;
363
364
234k
        if ( p_tkinfo->p_sp )
365
234k
            i_payload_dts -= VLC_TICK_FROM_MSFTIME(p_tkinfo->p_sp->i_time_offset);
366
367
234k
        if ( i_sub_payload_data_length &&
368
200k
             DemuxSubPayload( p_packetsys, i_stream_number, p_tkinfo,
369
200k
                              i_sub_payload_data_length, i_payload_pts, i_payload_dts,
370
200k
                              i_media_object_number, i_media_object_offset,
371
200k
                              b_packet_keyframe, b_ignore_pts ) < 0)
372
1
            return -1;
373
374
234k
        if ( pkt->left > pkt->i_skip + i_sub_payload_data_length )
375
227k
            pkt->left -= pkt->i_skip + i_sub_payload_data_length;
376
6.30k
        else
377
6.30k
            pkt->left = 0;
378
234k
        pkt->i_skip = 0;
379
234k
        if( pkt->left > 0 )
380
227k
        {
381
227k
            ssize_t i_return = vlc_stream_Peek( p_packetsys->s, &pkt->p_peek, pkt->left );
382
227k
            if ( i_return <= 0 || (size_t) i_return < pkt->left )
383
0
            {
384
0
                vlc_warning( p_packetsys->logger, "unexpected end of file" );
385
0
                return -1;
386
0
            }
387
227k
        }
388
389
234k
        if ( i_sub_payload_data_length <= i_payload_data_length )
390
234k
            i_payload_data_length -= i_sub_payload_data_length;
391
0
        else
392
0
            i_payload_data_length = 0;
393
394
234k
        i_subpayload_delta += i_pkt_time_delta;
395
234k
    }
396
397
14.5k
    return 0;
398
399
54.5k
skip:
400
54.5k
    pkt->i_skip += i_payload_data_length;
401
54.5k
    return 0;
402
18.7k
}
403
404
int DemuxASFPacket( asf_packet_sys_t *p_packetsys,
405
                    uint32_t i_data_packet_min, uint32_t i_data_packet_max,
406
                    uint64_t i_data_begin, uint64_t i_data_end )
407
1.60M
{
408
1.60M
    const uint64_t i_read_pos = vlc_stream_Tell( p_packetsys->s );
409
1.60M
    if( i_read_pos < i_data_begin ||
410
1.60M
        (i_data_end && ( i_data_packet_min > i_data_end ||
411
1.59M
                         i_read_pos > i_data_end - i_data_packet_min ) ) )
412
2.50k
        return 0;
413
414
1.59M
    const uint8_t *p_peek;
415
1.59M
    ssize_t i_return = vlc_stream_Peek( p_packetsys->s, &p_peek,i_data_packet_min );
416
1.59M
    if( i_return <= 0 || (size_t) i_return < i_data_packet_min )
417
126
    {
418
126
        vlc_warning( p_packetsys->logger, "unexpected end of file" );
419
126
        return 0;
420
126
    }
421
1.59M
    unsigned int i_skip = 0;
422
423
    /* *** parse error correction if present *** */
424
1.59M
    if( p_peek[0]&0x80 )
425
411k
    {
426
411k
        unsigned int i_error_correction_data_length = p_peek[0] & 0x0f;
427
411k
        unsigned int i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;
428
411k
        unsigned int i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03;
429
411k
        i_skip += 1; // skip error correction flags
430
431
411k
        if( i_error_correction_length_type != 0x00 ||
432
203k
            i_opaque_data_present != 0 ||
433
151k
            i_error_correction_data_length != 0x02 )
434
399k
        {
435
399k
            goto loop_error_recovery;
436
399k
        }
437
438
12.0k
        i_skip += i_error_correction_data_length;
439
12.0k
    }
440
1.18M
    else
441
1.59M
        vlc_warning( p_packetsys->logger, "no error correction" );
442
443
    /* sanity check */
444
1.20M
    if( i_skip + 2 >= i_data_packet_min )
445
1.17M
        goto loop_error_recovery;
446
447
26.7k
    asf_packet_t pkt;
448
26.7k
    int i_packet_flags = p_peek[i_skip]; i_skip++;
449
26.7k
    pkt.property = p_peek[i_skip]; i_skip++;
450
26.7k
    pkt.multiple = !!(i_packet_flags&0x01);
451
452
26.7k
    pkt.length = i_data_packet_min;
453
26.7k
    pkt.padding_length = 0;
454
455
26.7k
    if (GetValue2b(&pkt.length, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 5) < 0)
456
0
        goto loop_error_recovery;
457
26.7k
    uint32_t i_packet_sequence;
458
26.7k
    if (GetValue2b(&i_packet_sequence, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 1) < 0)
459
0
        goto loop_error_recovery;
460
26.7k
    if (GetValue2b(&pkt.padding_length, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 3) < 0)
461
15
        goto loop_error_recovery;
462
463
26.7k
    if( pkt.padding_length > pkt.length )
464
2.52k
    {
465
2.52k
        vlc_warning( p_packetsys->logger, "Too large padding: %"PRIu32, pkt.padding_length );
466
2.52k
        goto loop_error_recovery;
467
2.52k
    }
468
469
24.2k
    if( pkt.length < i_data_packet_min )
470
732
    {
471
        /* if packet length too short, there is extra padding */
472
732
        pkt.padding_length += i_data_packet_min - pkt.length;
473
732
        pkt.length = i_data_packet_min;
474
732
    }
475
476
24.2k
    if( i_skip + 4 > i_data_packet_min )
477
373
        goto loop_error_recovery;
478
479
23.8k
    pkt.send_time = VLC_TICK_FROM_MS(GetDWLE( p_peek + i_skip )); i_skip += 4;
480
23.8k
    /* uint16_t i_packet_duration = GetWLE( p_peek + i_skip ); */ i_skip += 2;
481
482
23.8k
    if( i_data_end &&
483
22.2k
        (pkt.length > i_data_end ||
484
22.0k
         i_read_pos > i_data_end - pkt.length) )
485
289
    {
486
289
        vlc_warning( p_packetsys->logger, "pkt size %"PRIu32" at %"PRIu64" does not fit data chunk size %"PRIu32,
487
289
                  pkt.length, i_read_pos, i_data_packet_max );
488
289
        return 0;
489
289
    }
490
491
23.5k
    i_return = vlc_stream_Peek( p_packetsys->s, &p_peek, pkt.length );
492
23.5k
    if( i_return <= 0 || pkt.length == 0 || (size_t)i_return < pkt.length )
493
74
    {
494
74
        vlc_warning( p_packetsys->logger, "unexpected end of file" );
495
74
        return 0;
496
74
    }
497
498
23.4k
    int i_payload_count = 1;
499
23.4k
    pkt.length_type = 0x02; //unused
500
23.4k
    if( pkt.multiple )
501
5.93k
    {
502
5.93k
        if( i_skip + 1 >= i_data_packet_min )
503
273
            goto loop_error_recovery;
504
5.66k
        i_payload_count = p_peek[i_skip] & 0x3f;
505
5.66k
        pkt.length_type = ( p_peek[i_skip] >> 6 )&0x03;
506
5.66k
        i_skip++;
507
5.66k
    }
508
509
23.2k
#ifdef ASF_DEBUG
510
23.2k
    vlc_debug( p_packetsys->logger, "%d payloads", i_payload_count);
511
23.2k
#endif
512
513
23.2k
    pkt.i_skip = i_skip;
514
23.2k
    pkt.p_peek = p_peek;
515
23.2k
    pkt.left = pkt.length;
516
517
92.3k
    for( int i_payload = 0; i_payload < i_payload_count ; i_payload++ )
518
70.7k
        if (DemuxPayload(p_packetsys, &pkt, i_payload) < 0)
519
1.56k
        {
520
1.56k
            vlc_warning( p_packetsys->logger, "payload err %d / %d", i_payload + 1, i_payload_count );
521
1.56k
            return 0;
522
1.56k
        }
523
524
21.6k
    if( pkt.left > 0 )
525
15.4k
    {
526
15.4k
        uint32_t toskip;
527
15.4k
        if( pkt.left > pkt.padding_length &&
528
12.0k
            !p_packetsys->b_can_hold_multiple_packets )
529
12.0k
        {
530
12.0k
            toskip = pkt.left;
531
12.0k
#ifdef ASF_DEBUG
532
12.0k
            vlc_warning( p_packetsys->logger, "Didn't read %"PRIu32" bytes in the packet at %"PRIu64,
533
12.0k
                            pkt.left - pkt.padding_length, vlc_stream_Tell(p_packetsys->s) );
534
12.0k
#endif
535
12.0k
        }
536
3.33k
        else if( pkt.left < pkt.padding_length )
537
157
        {
538
157
            toskip = 0;
539
157
#ifdef ASF_DEBUG
540
157
            vlc_warning( p_packetsys->logger, "Read %"PRIu32" too much bytes from the packet",
541
157
                               pkt.padding_length - pkt.left );
542
157
#endif
543
157
        }
544
3.17k
        else
545
3.17k
        {
546
3.17k
            toskip = pkt.padding_length;
547
3.17k
        }
548
549
15.4k
        if( toskip  && vlc_stream_Read( p_packetsys->s, NULL, toskip ) != toskip )
550
0
        {
551
0
            vlc_error( p_packetsys->logger, "cannot skip data, EOF ?" );
552
0
            return 0;
553
0
        }
554
15.4k
    }
555
556
21.6k
    return 1;
557
558
1.57M
loop_error_recovery:
559
1.57M
    vlc_warning( p_packetsys->logger, "unsupported packet header" );
560
1.57M
    if( i_data_packet_min != i_data_packet_max )
561
0
    {
562
0
        vlc_error( p_packetsys->logger, "unsupported packet header, fatal error" );
563
0
        return -1;
564
0
    }
565
1.57M
    if( vlc_stream_Read( p_packetsys->s, NULL, i_data_packet_min ) != i_data_packet_min )
566
0
    {
567
0
        vlc_warning( p_packetsys->logger, "cannot skip data, EOF ?" );
568
0
        return 0;
569
0
    }
570
571
1.57M
    return 1;
572
1.57M
}
573
574
void ASFPacketTrackInit( asf_track_info_t *p_ti )
575
11.2k
{
576
11.2k
    p_ti->i_cat = UNKNOWN_ES;
577
11.2k
    p_ti->p_esp = NULL;
578
11.2k
    p_ti->p_sp = NULL;
579
11.2k
    p_ti->p_frame = NULL;
580
11.2k
    p_ti->i_pktcount = 0;
581
11.2k
    p_ti->i_pkt = 0;
582
11.2k
}
583
584
void ASFPacketTrackReset( asf_track_info_t *p_ti )
585
11.2k
{
586
11.2k
    if( p_ti->p_frame )
587
1.61k
        block_ChainRelease( p_ti->p_frame );
588
    p_ti->p_frame = NULL;
589
11.2k
    p_ti->i_pktcount = 0;
590
11.2k
    p_ti->i_pkt = 0;
591
11.2k
}