Coverage Report

Created: 2025-07-18 08:04

/src/vlc/modules/demux/asf/asfpacket.c
Line
Count
Source (jump to first uncovered line)
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
208k
{
50
208k
    switch(bits&0x03)
51
208k
    {
52
81.0k
    case 1:
53
81.0k
        if (left < 1)
54
4
            return -1;
55
81.0k
        *var = p[*skip]; *skip += 1;
56
81.0k
        return 0;
57
34.4k
    case 2:
58
34.4k
        if (left < 2)
59
4
            return -1;
60
34.4k
        *var = GetWLE(&p[*skip]); *skip += 2;
61
34.4k
        return 0;
62
37.6k
    case 3:
63
37.6k
        if (left < 4)
64
5
            return -1;
65
37.6k
        *var = GetDWLE(&p[*skip]); *skip += 4;
66
37.6k
        return 0;
67
54.9k
    case 0:
68
54.9k
    default:
69
54.9k
        return 0;
70
208k
    }
71
208k
}
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
25.8k
{
79
25.8k
    block_t **pp_frame = &p_tkinfo->p_frame;
80
81
25.8k
    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
25.8k
    if( *pp_frame && i_media_object_offset == 0 )
106
15.5k
    {
107
15.5k
        p_packetsys->pf_send( p_packetsys, i_stream_number, pp_frame );
108
15.5k
    }
109
110
25.8k
    block_t *p_frag = vlc_stream_Block( p_packetsys->s, i_sub_payload_data_length );
111
25.8k
    if( p_frag == NULL ) {
112
0
        vlc_warning( p_packetsys->logger, "cannot read data" );
113
0
        return -1;
114
0
    }
115
116
25.8k
    p_frag->i_pts = (b_ignore_pts) ? VLC_TICK_INVALID : VLC_TICK_0 + i_pts;
117
25.8k
    p_frag->i_dts = VLC_TICK_0 + i_dts;
118
25.8k
    if ( b_keyframe )
119
3.85k
        p_frag->i_flags |= BLOCK_FLAG_TYPE_I;
120
121
25.8k
    block_ChainAppend( pp_frame, p_frag );
122
123
25.8k
    return 0;
124
25.8k
}
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
25.5k
{
131
25.5k
    if ( !p_tkinfo || !p_tkinfo->p_esp || !p_tkinfo->p_esp->p_ext )
132
3.23k
        return;
133
134
22.3k
    uint16_t i_payload_extensions_size;
135
22.3k
    asf_payload_extension_system_t *p_ext = NULL;
136
137
    /* Extensions always come in the declared order */
138
41.9k
    for ( int i=0; i< p_tkinfo->p_esp->i_payload_extension_system_count; i++ )
139
19.7k
    {
140
19.7k
        p_ext = &p_tkinfo->p_esp->p_ext[i];
141
19.7k
        if ( p_ext->i_data_size == 0xFFFF ) /* Variable length extension data */
142
0
        {
143
0
            if ( i_data < 2 ) return;
144
0
            i_payload_extensions_size = GetWLE( p_data );
145
0
            p_data += 2;
146
0
            i_data -= 2;
147
0
            i_payload_extensions_size = 0;
148
0
        }
149
19.7k
        else
150
19.7k
        {
151
19.7k
            i_payload_extensions_size = p_ext->i_data_size;
152
19.7k
        }
153
154
19.7k
        if ( i_data < i_payload_extensions_size ) return;
155
156
19.6k
        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
19.6k
        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
19.6k
        else if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_pixelaspectratio_guid ) &&
176
19.6k
                  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
19.6k
        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
19.6k
        i_data -= i_payload_extensions_size;
195
19.6k
        p_data += i_payload_extensions_size;
196
19.6k
    }
197
198
22.2k
    return;
199
200
22.2k
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
43.9k
{
207
#ifndef ASF_DEBUG
208
    VLC_UNUSED( i_payload );
209
#endif
210
43.9k
    if( ! pkt->left || pkt->i_skip >= pkt->left )
211
48
        return -1;
212
213
43.8k
    bool b_packet_keyframe = pkt->p_peek[pkt->i_skip] >> 7;
214
43.8k
    uint8_t i_stream_number = pkt->p_peek[pkt->i_skip++] & 0x7f;
215
216
43.8k
    uint32_t i_media_object_number = 0;
217
43.8k
    if (GetValue2b(&i_media_object_number, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 4) < 0)
218
7
        return -1;
219
43.8k
    uint32_t i_media_object_offset = 0;
220
43.8k
    if (GetValue2b(&i_media_object_offset, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 2) < 0)
221
3
        return -1;
222
43.8k
    uint32_t i_replicated_data_length = 0;
223
43.8k
    if (GetValue2b(&i_replicated_data_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property) < 0)
224
3
        return -1;
225
226
43.8k
    vlc_tick_t i_pkt_time;
227
43.8k
    vlc_tick_t i_pkt_time_delta = 0;
228
43.8k
    uint32_t i_payload_data_length = 0;
229
43.8k
    uint32_t i_temp_payload_length = 0;
230
231
    /* First packet, in case we do not have index to guess preroll start time */
232
43.8k
    if ( *p_packetsys->pi_preroll_start == ASFPACKET_PREROLL_FROM_CURRENT )
233
0
        *p_packetsys->pi_preroll_start = pkt->send_time;
234
235
43.8k
    asf_track_info_t *p_tkinfo = p_packetsys->pf_gettrackinfo( p_packetsys, i_stream_number );
236
43.8k
    if ( !p_tkinfo )
237
17.9k
        goto skip;
238
239
25.9k
    bool b_ignore_pts = (p_tkinfo->i_cat == VIDEO_ES); /* ignore PTS delta with video when not set by mux */
240
241
25.9k
    if( pkt->left - pkt->i_skip < i_replicated_data_length )
242
46
        return -1;
243
244
    /* Non compressed */
245
25.8k
    if( i_replicated_data_length > 7 ) // should be at least 8 bytes
246
25.5k
    {
247
        /* Followed by 2 optional DWORDS, offset in media and *media* presentation time */
248
25.5k
        i_pkt_time = VLC_TICK_FROM_MS(GetDWLE( pkt->p_peek + pkt->i_skip + 4 ));
249
250
        /* Parsing extensions, See 7.3.1 */
251
25.5k
        ParsePayloadExtensions( p_packetsys, p_tkinfo,
252
25.5k
                                &pkt->p_peek[pkt->i_skip + 8],
253
25.5k
                                i_replicated_data_length - 8,
254
25.5k
                                &b_packet_keyframe );
255
25.5k
        i_pkt_time -= *p_packetsys->pi_preroll;
256
25.5k
        pkt->i_skip += i_replicated_data_length;
257
25.5k
    }
258
325
    else if ( i_replicated_data_length == 0 )
259
270
    {
260
        /* optional DWORDS missing */
261
270
        i_pkt_time = pkt->send_time;
262
270
    }
263
    /* Compressed payload */
264
55
    else if( i_replicated_data_length == 1 )
265
22
    {
266
        /* i_media_object_offset is *media* presentation time */
267
        /* Next byte is *media* Presentation Time Delta */
268
22
        i_pkt_time_delta = VLC_TICK_FROM_MS(pkt->p_peek[pkt->i_skip]);
269
22
        b_ignore_pts = false;
270
22
        i_pkt_time = VLC_TICK_FROM_MS(i_media_object_offset);
271
22
        i_pkt_time -= *p_packetsys->pi_preroll;
272
22
        pkt->i_skip++;
273
22
        i_media_object_offset = 0;
274
22
    }
275
33
    else
276
33
    {
277
        /* >1 && <8 Invalid replicated length ! */
278
33
        vlc_warning( p_packetsys->logger, "Invalid replicated data length detected." );
279
33
        if( pkt->length - pkt->i_skip < pkt->padding_length )
280
2
            return -1;
281
282
31
        i_payload_data_length = pkt->length - pkt->padding_length - pkt->i_skip;
283
31
        goto skip;
284
33
    }
285
286
25.8k
    if( ! pkt->left || pkt->i_skip >= pkt->left )
287
0
        return -1;
288
289
25.8k
    bool b_preroll_done = ( pkt->send_time > (*p_packetsys->pi_preroll_start + *p_packetsys->pi_preroll) );
290
291
25.8k
    if (i_pkt_time < 0) i_pkt_time = 0; // FIXME?
292
293
25.8k
    if( pkt->multiple ) {
294
21.7k
        if (GetValue2b(&i_temp_payload_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->length_type) < 0)
295
0
            return -1;
296
21.7k
    }
297
4.11k
    else
298
4.11k
    {
299
4.11k
        if( pkt->length - pkt->i_skip < pkt->padding_length )
300
3
            return -1;
301
4.11k
        i_temp_payload_length = pkt->length - pkt->padding_length - pkt->i_skip;
302
4.11k
    }
303
304
25.8k
    i_payload_data_length = i_temp_payload_length;
305
306
25.8k
#ifdef ASF_DEBUG
307
25.8k
     vlc_debug( p_packetsys->logger,
308
25.8k
              "payload(%d) stream_number:%"PRIu8" media_object_number:%d media_object_offset:%"PRIu32
309
25.8k
                " replicated_data_length:%"PRIu32" payload_data_length %"PRIu32,
310
25.8k
              i_payload + 1, i_stream_number, i_media_object_number,
311
25.8k
              i_media_object_offset, i_replicated_data_length, i_payload_data_length );
312
25.8k
     vlc_debug( p_packetsys->logger,
313
25.8k
              "  pkttime=%"PRId64" st=%"PRId64,
314
25.8k
              i_pkt_time, MS_FROM_VLC_TICK(pkt->send_time) );
315
25.8k
#endif
316
317
25.8k
     if( ! i_payload_data_length || i_payload_data_length > pkt->left )
318
116
     {
319
116
         vlc_debug( p_packetsys->logger, "  payload length problem %d %"PRIu32
320
116
                    " %"PRIu32, pkt->multiple, i_payload_data_length, pkt->left );
321
116
         return -1;
322
116
     }
323
324
25.7k
    if ( p_packetsys->pf_doskip &&
325
25.7k
         p_packetsys->pf_doskip( p_packetsys, i_stream_number, b_packet_keyframe ) )
326
355
        goto skip;
327
328
25.3k
    if ( b_preroll_done )
329
13.2k
    {
330
13.2k
        vlc_tick_t i_track_time = i_pkt_time;
331
332
13.2k
        if ( p_packetsys->pf_updatetime )
333
13.2k
            p_packetsys->pf_updatetime( p_packetsys, i_stream_number, i_track_time );
334
13.2k
    }
335
336
25.3k
    if( p_packetsys->pf_updatesendtime )
337
25.3k
        p_packetsys->pf_updatesendtime( p_packetsys, pkt->send_time );
338
339
25.3k
    vlc_tick_t i_subpayload_delta = 0;
340
52.4k
    while (i_payload_data_length && pkt->i_skip < pkt->left )
341
27.0k
    {
342
27.0k
        uint32_t i_sub_payload_data_length = i_payload_data_length;
343
27.0k
        if( i_replicated_data_length == 1 )
344
1.71k
        {
345
1.71k
            i_sub_payload_data_length = pkt->p_peek[pkt->i_skip++];
346
1.71k
            i_payload_data_length--;
347
1.71k
            if( i_sub_payload_data_length > i_payload_data_length )
348
17
                goto skip;
349
1.71k
        }
350
351
27.0k
        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
27.0k
        vlc_tick_t i_payload_pts;
358
27.0k
        i_payload_pts = i_pkt_time + i_subpayload_delta;
359
27.0k
        if ( p_tkinfo->p_sp )
360
27.0k
            i_payload_pts -= VLC_TICK_FROM_MSFTIME(p_tkinfo->p_sp->i_time_offset);
361
362
27.0k
        vlc_tick_t i_payload_dts = i_pkt_time;
363
364
27.0k
        if ( p_tkinfo->p_sp )
365
27.0k
            i_payload_dts -= VLC_TICK_FROM_MSFTIME(p_tkinfo->p_sp->i_time_offset);
366
367
27.0k
        if ( i_sub_payload_data_length &&
368
27.0k
             DemuxSubPayload( p_packetsys, i_stream_number, p_tkinfo,
369
25.8k
                              i_sub_payload_data_length, i_payload_pts, i_payload_dts,
370
25.8k
                              i_media_object_number, i_media_object_offset,
371
25.8k
                              b_packet_keyframe, b_ignore_pts ) < 0)
372
0
            return -1;
373
374
27.0k
        if ( pkt->left > pkt->i_skip + i_sub_payload_data_length )
375
25.1k
            pkt->left -= pkt->i_skip + i_sub_payload_data_length;
376
1.94k
        else
377
1.94k
            pkt->left = 0;
378
27.0k
        pkt->i_skip = 0;
379
27.0k
        if( pkt->left > 0 )
380
25.1k
        {
381
25.1k
            ssize_t i_return = vlc_stream_Peek( p_packetsys->s, &pkt->p_peek, pkt->left );
382
25.1k
            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
25.1k
        }
388
389
27.0k
        if ( i_sub_payload_data_length <= i_payload_data_length )
390
27.0k
            i_payload_data_length -= i_sub_payload_data_length;
391
0
        else
392
0
            i_payload_data_length = 0;
393
394
27.0k
        i_subpayload_delta += i_pkt_time_delta;
395
27.0k
    }
396
397
25.3k
    return 0;
398
399
18.3k
skip:
400
18.3k
    pkt->i_skip += i_payload_data_length;
401
18.3k
    return 0;
402
25.3k
}
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
776k
{
408
776k
    const uint64_t i_read_pos = vlc_stream_Tell( p_packetsys->s );
409
776k
    if( i_read_pos < i_data_begin ||
410
776k
        (i_data_end && ( i_data_packet_min > i_data_end ||
411
775k
                         i_read_pos > i_data_end - i_data_packet_min ) ) )
412
1.03k
        return 0;
413
414
775k
    const uint8_t *p_peek;
415
775k
    ssize_t i_return = vlc_stream_Peek( p_packetsys->s, &p_peek,i_data_packet_min );
416
775k
    if( i_return <= 0 || (size_t) i_return < i_data_packet_min )
417
32
    {
418
32
        vlc_warning( p_packetsys->logger, "unexpected end of file" );
419
32
        return 0;
420
32
    }
421
775k
    unsigned int i_skip = 0;
422
423
    /* *** parse error correction if present *** */
424
775k
    if( p_peek[0]&0x80 )
425
317k
    {
426
317k
        unsigned int i_error_correction_data_length = p_peek[0] & 0x0f;
427
317k
        unsigned int i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;
428
317k
        unsigned int i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03;
429
317k
        i_skip += 1; // skip error correction flags
430
431
317k
        if( i_error_correction_length_type != 0x00 ||
432
317k
            i_opaque_data_present != 0 ||
433
317k
            i_error_correction_data_length != 0x02 )
434
294k
        {
435
294k
            goto loop_error_recovery;
436
294k
        }
437
438
23.3k
        i_skip += i_error_correction_data_length;
439
23.3k
    }
440
457k
    else
441
775k
        vlc_warning( p_packetsys->logger, "no error correction" );
442
443
    /* sanity check */
444
480k
    if( i_skip + 2 >= i_data_packet_min )
445
462k
        goto loop_error_recovery;
446
447
18.2k
    asf_packet_t pkt;
448
18.2k
    int i_packet_flags = p_peek[i_skip]; i_skip++;
449
18.2k
    pkt.property = p_peek[i_skip]; i_skip++;
450
18.2k
    pkt.multiple = !!(i_packet_flags&0x01);
451
452
18.2k
    pkt.length = i_data_packet_min;
453
18.2k
    pkt.padding_length = 0;
454
455
18.2k
    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
18.2k
    uint32_t i_packet_sequence;
458
18.2k
    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
18.2k
    if (GetValue2b(&pkt.padding_length, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 3) < 0)
461
0
        goto loop_error_recovery;
462
463
18.2k
    if( pkt.padding_length > pkt.length )
464
1.08k
    {
465
1.08k
        vlc_warning( p_packetsys->logger, "Too large padding: %"PRIu32, pkt.padding_length );
466
1.08k
        goto loop_error_recovery;
467
1.08k
    }
468
469
17.1k
    if( pkt.length < i_data_packet_min )
470
567
    {
471
        /* if packet length too short, there is extra padding */
472
567
        pkt.padding_length += i_data_packet_min - pkt.length;
473
567
        pkt.length = i_data_packet_min;
474
567
    }
475
476
17.1k
    if( i_skip + 4 > i_data_packet_min )
477
0
        goto loop_error_recovery;
478
479
17.1k
    pkt.send_time = VLC_TICK_FROM_MS(GetDWLE( p_peek + i_skip )); i_skip += 4;
480
17.1k
    /* uint16_t i_packet_duration = GetWLE( p_peek + i_skip ); */ i_skip += 2;
481
482
17.1k
    if( i_data_end &&
483
17.1k
        (pkt.length > i_data_end ||
484
16.9k
         i_read_pos > i_data_end - pkt.length) )
485
188
    {
486
188
        vlc_warning( p_packetsys->logger, "pkt size %"PRIu32" at %"PRIu64" does not fit data chunk size %"PRIu32,
487
188
                  pkt.length, i_read_pos, i_data_packet_max );
488
188
        return 0;
489
188
    }
490
491
16.9k
    i_return = vlc_stream_Peek( p_packetsys->s, &p_peek, pkt.length );
492
16.9k
    if( i_return <= 0 || pkt.length == 0 || (size_t)i_return < pkt.length )
493
18
    {
494
18
        vlc_warning( p_packetsys->logger, "unexpected end of file" );
495
18
        return 0;
496
18
    }
497
498
16.9k
    int i_payload_count = 1;
499
16.9k
    pkt.length_type = 0x02; //unused
500
16.9k
    if( pkt.multiple )
501
9.23k
    {
502
9.23k
        if( i_skip + 1 >= i_data_packet_min )
503
0
            goto loop_error_recovery;
504
9.23k
        i_payload_count = p_peek[i_skip] & 0x3f;
505
9.23k
        pkt.length_type = ( p_peek[i_skip] >> 6 )&0x03;
506
9.23k
        i_skip++;
507
9.23k
    }
508
509
16.9k
#ifdef ASF_DEBUG
510
16.9k
    vlc_debug( p_packetsys->logger, "%d payloads", i_payload_count);
511
16.9k
#endif
512
513
16.9k
    pkt.i_skip = i_skip;
514
16.9k
    pkt.p_peek = p_peek;
515
16.9k
    pkt.left = pkt.length;
516
517
60.6k
    for( int i_payload = 0; i_payload < i_payload_count ; i_payload++ )
518
43.9k
        if (DemuxPayload(p_packetsys, &pkt, i_payload) < 0)
519
228
        {
520
228
            vlc_warning( p_packetsys->logger, "payload err %d / %d", i_payload + 1, i_payload_count );
521
228
            return 0;
522
228
        }
523
524
16.7k
    if( pkt.left > 0 )
525
14.8k
    {
526
14.8k
        uint32_t toskip;
527
14.8k
        if( pkt.left > pkt.padding_length &&
528
14.8k
            !p_packetsys->b_can_hold_multiple_packets )
529
4.70k
        {
530
4.70k
            toskip = pkt.left;
531
4.70k
#ifdef ASF_DEBUG
532
4.70k
            vlc_warning( p_packetsys->logger, "Didn't read %"PRIu32" bytes in the packet at %"PRIu64,
533
4.70k
                            pkt.left - pkt.padding_length, vlc_stream_Tell(p_packetsys->s) );
534
4.70k
#endif
535
4.70k
        }
536
10.1k
        else if( pkt.left < pkt.padding_length )
537
36
        {
538
36
            toskip = 0;
539
36
#ifdef ASF_DEBUG
540
36
            vlc_warning( p_packetsys->logger, "Read %"PRIu32" too much bytes from the packet",
541
36
                               pkt.padding_length - pkt.left );
542
36
#endif
543
36
        }
544
10.0k
        else
545
10.0k
        {
546
10.0k
            toskip = pkt.padding_length;
547
10.0k
        }
548
549
14.8k
        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
14.8k
    }
555
556
16.7k
    return 1;
557
558
758k
loop_error_recovery:
559
758k
    vlc_warning( p_packetsys->logger, "unsupported packet header" );
560
758k
    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
758k
    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
758k
    return 1;
572
758k
}
573
574
void ASFPacketTrackInit( asf_track_info_t *p_ti )
575
9.45k
{
576
9.45k
    p_ti->i_cat = UNKNOWN_ES;
577
9.45k
    p_ti->p_esp = NULL;
578
9.45k
    p_ti->p_sp = NULL;
579
9.45k
    p_ti->p_frame = NULL;
580
9.45k
    p_ti->i_pktcount = 0;
581
9.45k
    p_ti->i_pkt = 0;
582
9.45k
}
583
584
void ASFPacketTrackReset( asf_track_info_t *p_ti )
585
9.45k
{
586
9.45k
    if( p_ti->p_frame )
587
794
        block_ChainRelease( p_ti->p_frame );
588
9.45k
    p_ti->p_frame = NULL;
589
9.45k
    p_ti->i_pktcount = 0;
590
9.45k
    p_ti->i_pkt = 0;
591
9.45k
}