Coverage Report

Created: 2023-06-07 06:30

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