Coverage Report

Created: 2026-11-12 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/packetizer/mpegvideo.c
Line
Count
Source
1
/*****************************************************************************
2
 * mpegvideo.c: parse and packetize an MPEG1/2 video stream
3
 *****************************************************************************
4
 * Copyright (C) 2001-2006 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Eric Petit <titer@videolan.org>
8
 *          Gildas Bazin <gbazin@videolan.org>
9
 *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
10
 *
11
 * This program is free software; you can redistribute it and/or modify it
12
 * under the terms of the GNU Lesser General Public License as published by
13
 * the Free Software Foundation; either version 2.1 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Lesser General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Lesser General Public License
22
 * along with this program; if not, write to the Free Software Foundation,
23
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
 *****************************************************************************/
25
26
/*****************************************************************************
27
 * Problem with this implementation:
28
 *
29
 * Although we should time-stamp each picture with a PTS, this isn't possible
30
 * with the current implementation.
31
 * The problem comes from the fact that for non-low-delay streams we can't
32
 * calculate the PTS of pictures used as backward reference. Even the temporal
33
 * reference number doesn't help here because all the pictures don't
34
 * necessarily have the same duration (eg. 3:2 pulldown).
35
 *
36
 * However this doesn't really matter as far as the MPEG muxers are concerned
37
 * because they allow having empty PTS fields. --gibalou
38
 *****************************************************************************/
39
40
/*****************************************************************************
41
 * Preamble
42
 *****************************************************************************/
43
44
#ifdef HAVE_CONFIG_H
45
# include "config.h"
46
#endif
47
48
#include <vlc_common.h>
49
#include <vlc_plugin.h>
50
#include <vlc_block.h>
51
#include <vlc_codec.h>
52
#include <vlc_block_helper.h>
53
#include "mpegvideo.h"
54
#include "../codec/cc.h"
55
#include "packetizer_helper.h"
56
#include "startcode_helper.h"
57
#include "h26x_nal_common.h"
58
59
#include <limits.h>
60
#include <stdckdint.h>
61
62
#define SYNC_INTRAFRAME_TEXT N_("Sync on Intra Frame")
63
#define SYNC_INTRAFRAME_LONGTEXT N_("Normally the packetizer would " \
64
    "sync on the next full frame. This flags instructs the packetizer " \
65
    "to sync on the first Intra Frame found.")
66
67
/*****************************************************************************
68
 * Module descriptor
69
 *****************************************************************************/
70
static int  Open ( vlc_object_t * );
71
static void Close( vlc_object_t * );
72
73
178
vlc_module_begin ()
74
89
    set_subcategory( SUBCAT_SOUT_PACKETIZER )
75
89
    set_description( N_("MPEG-I/II video packetizer") )
76
89
    set_shortname( N_("MPEG Video") )
77
89
    set_capability( "video packetizer", 50 )
78
178
    set_callbacks( Open, Close )
79
80
89
    add_bool( "packetizer-mpegvideo-sync-iframe", false, SYNC_INTRAFRAME_TEXT,
81
89
              SYNC_INTRAFRAME_LONGTEXT )
82
89
vlc_module_end ()
83
84
enum mpeg_startcode_e
85
{
86
    PICTURE_STARTCODE          = 0x00,
87
    SLICE_STARTCODE_FIRST      = 0x01,
88
    SLICE_STARTCODE_LAST       = 0xAF,
89
    USER_DATA_STARTCODE        = 0xB2,
90
    SEQUENCE_HEADER_STARTCODE  = 0xB3,
91
    SEQUENCE_ERROR_STARTCODE   = 0xB4,
92
    EXTENSION_STARTCODE        = 0xB5,
93
    SEQUENCE_END_STARTCODE     = 0xB7,
94
    GROUP_STARTCODE            = 0xB8,
95
    SYSTEM_STARTCODE_FIRST     = 0xB9,
96
    SYSTEM_STARTCODE_LAST      = 0xFF,
97
};
98
99
enum extension_start_code_identifier_e
100
{
101
    SEQUENCE_EXTENSION_ID                   = 0x01,
102
    SEQUENCE_DISPLAY_EXTENSION_ID           = 0x02,
103
    QUANT_MATRIX_EXTENSION_ID               = 0x03,
104
    COPYRIGHT_EXTENSION_ID                  = 0x04,
105
    SEQUENCE_SCALABLE_EXTENSION_ID          = 0x05,
106
    PICTURE_DISPLAY_EXTENSION_ID            = 0x07,
107
    PICTURE_CODING_EXTENSION_ID             = 0x08,
108
    PICTURE_SPATIAL_SCALABLE_EXTENSION_ID   = 0x09,
109
    PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID  = 0x0A,
110
    CAMERA_PARAMETERS_EXTENSION_ID          = 0x0B,
111
    ITU_T_EXTENSION_ID                      = 0x0C,
112
};
113
114
/*****************************************************************************
115
 * Local prototypes
116
 *****************************************************************************/
117
typedef struct
118
{
119
    /*
120
     * Input properties
121
     */
122
    packetizer_t packetizer;
123
124
    /* Sequence header and extension */
125
    block_t *p_seq;
126
    block_t *p_ext;
127
128
    /* Current frame being built */
129
    block_t    *p_frame;
130
    block_t    **pp_last;
131
132
    bool b_frame_slice;
133
    vlc_tick_t i_pts;
134
    vlc_tick_t i_dts;
135
136
    date_t  dts;
137
    date_t  prev_iframe_dts;
138
139
    /* Sequence properties */
140
    uint16_t i_h_size_value;
141
    uint16_t i_v_size_value;
142
    uint8_t  i_aspect_ratio_info;
143
    uint8_t  i_frame_rate_value;
144
    uint32_t i_bitratelower18;
145
    /* Extended Sequence properties (MPEG2) */
146
    uint8_t  i_h_size_ext;
147
    uint8_t  i_v_size_ext;
148
    uint16_t i_bitrateupper12;
149
    bool  b_seq_progressive;
150
    bool  b_low_delay;
151
    uint8_t i_frame_rate_ext_n;
152
    uint8_t i_frame_rate_ext_d;
153
154
    /* Picture properties */
155
    int i_temporal_ref;
156
    int i_prev_temporal_ref;
157
    int i_picture_type;
158
    int i_picture_structure;
159
    int i_top_field_first;
160
    int i_repeat_first_field;
161
    int i_progressive_frame;
162
163
    vlc_tick_t i_last_ref_pts;
164
165
    vlc_tick_t i_last_frame_pts;
166
    uint16_t i_last_frame_refid;
167
168
    bool b_second_field;
169
170
    /* Number of pictures since last sequence header */
171
    unsigned i_seq_old;
172
173
    /* Sync behaviour */
174
    bool  b_sync_on_intra_frame;
175
    bool  b_waiting_iframe;
176
    int   i_next_block_flags;
177
178
    /* */
179
    bool b_cc_reset;
180
    uint32_t i_cc_flags;
181
    vlc_tick_t i_cc_pts;
182
    vlc_tick_t i_cc_dts;
183
    cc_data_t cc;
184
} decoder_sys_t;
185
186
static block_t *Packetize( decoder_t *, block_t ** );
187
static void PacketizeFlush( decoder_t * );
188
static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t * );
189
190
static void PacketizeReset( void *p_private, bool b_broken );
191
static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * );
192
static int PacketizeValidate( void *p_private, block_t * );
193
static block_t * PacketizeDrain( void *p_private );
194
195
static block_t *ParseMPEGBlock( decoder_t *, block_t * );
196
197
static const uint8_t p_mp2v_startcode[3] = { 0x00, 0x00, 0x01 };
198
199
/*****************************************************************************
200
 * Open:
201
 *****************************************************************************/
202
static int Open( vlc_object_t *p_this )
203
126k
{
204
126k
    decoder_t *p_dec = (decoder_t*)p_this;
205
126k
    decoder_sys_t *p_sys;
206
207
126k
    if( p_dec->fmt_in->i_codec != VLC_CODEC_MPGV &&
208
54.6k
        p_dec->fmt_in->i_codec != VLC_CODEC_MP2V )
209
53.1k
        return VLC_EGENERIC;
210
211
73.5k
    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
212
73.5k
    if( !p_dec->p_sys )
213
0
        return VLC_ENOMEM;
214
73.5k
    memset( p_dec->p_sys, 0, sizeof( decoder_sys_t ) );
215
216
73.5k
    p_dec->fmt_out.i_codec = VLC_CODEC_MPGV;
217
73.5k
    p_dec->fmt_out.i_original_fourcc = p_dec->fmt_in->i_original_fourcc;
218
219
    /* Misc init */
220
73.5k
    packetizer_Init( &p_sys->packetizer,
221
73.5k
                     p_mp2v_startcode, sizeof(p_mp2v_startcode), startcode_FindAnnexB,
222
73.5k
                     NULL, 0, 4,
223
73.5k
                     PacketizeReset, PacketizeParse, PacketizeValidate, PacketizeDrain,
224
73.5k
                     p_dec );
225
226
73.5k
    p_sys->p_seq = NULL;
227
73.5k
    p_sys->p_ext = NULL;
228
73.5k
    p_sys->p_frame = NULL;
229
73.5k
    p_sys->pp_last = &p_sys->p_frame;
230
73.5k
    p_sys->b_frame_slice = false;
231
232
73.5k
    p_sys->i_dts =
233
73.5k
    p_sys->i_pts = VLC_TICK_INVALID;
234
235
73.5k
    unsigned num, den;
236
73.5k
    if( p_dec->fmt_in->video.i_frame_rate && p_dec->fmt_in->video.i_frame_rate_base &&
237
14
        !ckd_mul(&num, p_dec->fmt_in->video.i_frame_rate, 2) )
238
14
    {
239
14
        num = p_dec->fmt_in->video.i_frame_rate;
240
14
        den = p_dec->fmt_in->video.i_frame_rate_base;
241
14
    }
242
73.4k
    else
243
73.4k
    {
244
73.4k
        num = 30000;
245
73.4k
        den = 1001;
246
73.4k
    }
247
73.5k
    date_Init( &p_sys->dts, 2 * num, den ); /* fields / den */
248
73.5k
    date_Init( &p_sys->prev_iframe_dts, 2 * num, den );
249
250
73.5k
    p_sys->i_h_size_value = 0;
251
73.5k
    p_sys->i_v_size_value = 0;
252
73.5k
    p_sys->i_aspect_ratio_info = 0;
253
73.5k
    p_sys->i_frame_rate_value = 0;
254
73.5k
    p_sys->i_bitratelower18 = 0;
255
73.5k
    p_sys->i_bitrateupper12 = 0;
256
73.5k
    p_sys->i_h_size_ext = 0;
257
73.5k
    p_sys->i_v_size_ext = 0;
258
73.5k
    p_sys->b_seq_progressive = true;
259
73.5k
    p_sys->b_low_delay = false;
260
73.5k
    p_sys->i_frame_rate_ext_n = 0;
261
73.5k
    p_sys->i_frame_rate_ext_d = 0;
262
73.5k
    p_sys->i_seq_old = 0;
263
264
73.5k
    p_sys->i_temporal_ref = 0;
265
73.5k
    p_sys->i_prev_temporal_ref = 2048;
266
73.5k
    p_sys->i_picture_type = 0;
267
73.5k
    p_sys->i_picture_structure = 0x03; /* frame */
268
73.5k
    p_sys->i_top_field_first = 0;
269
73.5k
    p_sys->i_repeat_first_field = 0;
270
73.5k
    p_sys->i_progressive_frame = 0;
271
272
73.5k
    p_sys->i_last_ref_pts = VLC_TICK_INVALID;
273
73.5k
    p_sys->b_second_field = 0;
274
275
73.5k
    p_sys->i_next_block_flags = 0;
276
277
73.5k
    p_sys->i_last_frame_refid = 0;
278
279
73.5k
    p_sys->b_waiting_iframe =
280
73.5k
    p_sys->b_sync_on_intra_frame = var_CreateGetBool( p_dec, "packetizer-mpegvideo-sync-iframe" );
281
73.5k
    if( p_sys->b_sync_on_intra_frame )
282
73.5k
        msg_Dbg( p_dec, "syncing on intra frame now" );
283
284
73.5k
    p_sys->b_cc_reset = false;
285
73.5k
    p_sys->i_cc_pts = 0;
286
73.5k
    p_sys->i_cc_dts = 0;
287
73.5k
    p_sys->i_cc_flags = 0;
288
73.5k
    cc_Init( &p_sys->cc );
289
290
73.5k
    p_dec->pf_packetize = Packetize;
291
73.5k
    p_dec->pf_flush = PacketizeFlush;
292
73.5k
    p_dec->pf_get_cc = GetCc;
293
294
73.5k
    return VLC_SUCCESS;
295
73.5k
}
296
297
/*****************************************************************************
298
 * Close:
299
 *****************************************************************************/
300
static void Close( vlc_object_t *p_this )
301
73.5k
{
302
73.5k
    decoder_t     *p_dec = (decoder_t*)p_this;
303
73.5k
    decoder_sys_t *p_sys = p_dec->p_sys;
304
305
73.5k
    if( p_sys->p_seq )
306
10.3k
    {
307
10.3k
        block_Release( p_sys->p_seq );
308
10.3k
    }
309
73.5k
    if( p_sys->p_ext )
310
3.38k
    {
311
3.38k
        block_Release( p_sys->p_ext );
312
3.38k
    }
313
73.5k
    if( p_sys->p_frame )
314
10.3k
    {
315
10.3k
        block_ChainRelease( p_sys->p_frame );
316
10.3k
    }
317
73.5k
    packetizer_Clean( &p_sys->packetizer );
318
319
73.5k
    var_Destroy( p_dec, "packetizer-mpegvideo-sync-iframe" );
320
321
73.5k
    free( p_sys );
322
73.5k
}
323
324
/*****************************************************************************
325
 * Packetize:
326
 *****************************************************************************/
327
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
328
1.41M
{
329
1.41M
    decoder_sys_t *p_sys = p_dec->p_sys;
330
331
1.41M
    return packetizer_Packetize( &p_sys->packetizer, pp_block );
332
1.41M
}
333
334
static void PacketizeFlush( decoder_t *p_dec )
335
0
{
336
0
    decoder_sys_t *p_sys = p_dec->p_sys;
337
338
0
    packetizer_Flush( &p_sys->packetizer );
339
0
}
340
341
/*****************************************************************************
342
 * GetCc:
343
 *****************************************************************************/
344
static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t *p_desc )
345
400k
{
346
400k
    decoder_sys_t *p_sys = p_dec->p_sys;
347
400k
    block_t *p_cc;
348
349
400k
    if( !p_sys->cc.b_reorder && p_sys->cc.i_data <= 0 )
350
269k
        return NULL;
351
352
131k
    p_cc = block_Alloc( p_sys->cc.i_data );
353
131k
    if( p_cc )
354
131k
    {
355
131k
        memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data );
356
131k
        p_cc->i_dts =
357
131k
        p_cc->i_pts = p_sys->cc.b_reorder ? p_sys->i_cc_pts : p_sys->i_cc_dts;
358
131k
        p_cc->i_flags = p_sys->i_cc_flags & BLOCK_FLAG_TYPE_MASK;
359
360
131k
        p_desc->i_608_channels = p_sys->cc.i_608channels;
361
131k
        p_desc->i_708_channels = p_sys->cc.i_708channels;
362
131k
        p_desc->i_reorder_depth = p_sys->cc.b_reorder ? 0 : -1;
363
131k
    }
364
131k
    cc_Flush( &p_sys->cc );
365
131k
    return p_cc;
366
400k
}
367
368
/*****************************************************************************
369
 * ProcessSequenceParameters
370
 *****************************************************************************/
371
static void ProcessSequenceParameters( decoder_t *p_dec )
372
706k
{
373
706k
    decoder_sys_t *p_sys = p_dec->p_sys;
374
706k
    video_format_t *fmt = &p_dec->fmt_out.video;
375
376
    /* Picture size */
377
706k
    fmt->i_visible_width = p_sys->i_h_size_value + (p_sys->i_h_size_ext << 14);
378
706k
    fmt->i_width = (fmt->i_visible_width + 0x0F) & ~0x0F;
379
706k
    fmt->i_visible_height = p_sys->i_v_size_value + (p_sys->i_v_size_ext << 14);
380
706k
    if( p_sys->b_seq_progressive )
381
314k
        fmt->i_height = (fmt->i_visible_height + 0x0F) & ~0x0F;
382
392k
    else
383
392k
        fmt->i_height = (fmt->i_visible_height + 0x1F) & ~0x1F;
384
385
    /* Bitrate */
386
706k
    if( p_dec->fmt_out.i_bitrate == 0 )
387
159k
        p_dec->fmt_out.i_bitrate = ((p_sys->i_bitrateupper12 << 18) |
388
159k
                                    p_sys->i_bitratelower18) * 400;
389
390
    /* Frame Rate */
391
392
    /* Only of not specified by container */
393
706k
    if ( !p_dec->fmt_in->video.i_frame_rate ||
394
1.04k
         !p_dec->fmt_in->video.i_frame_rate_base )
395
706k
    {
396
706k
        static const int code_to_frame_rate[16][2] =
397
706k
        {
398
706k
            { 1, 1 },  /* invalid */
399
706k
            { 24000, 1001 }, { 24, 1 }, { 25, 1 },       { 30000, 1001 },
400
706k
            { 30, 1 },       { 50, 1 }, { 60000, 1001 }, { 60, 1 },
401
            /* Unofficial 15fps from Xing*/
402
706k
            { 15, 1 },
403
            /* Unofficial economy rates from libmpeg3 */
404
706k
            { 5, 1 }, { 10, 1 }, { 12, 1 }, { 15, 1 },
405
706k
            { 1, 1 },  { 1, 1 }  /* invalid */
406
706k
        };
407
408
        /* frames / den */
409
706k
        unsigned num = code_to_frame_rate[p_sys->i_frame_rate_value][0] << 1;
410
706k
        unsigned den = code_to_frame_rate[p_sys->i_frame_rate_value][1];
411
706k
        if( p_sys->i_frame_rate_ext_n || p_sys->i_frame_rate_ext_d )
412
463k
        {
413
463k
            vlc_ureduce( &num, &den,
414
463k
                         num * (1 + p_sys->i_frame_rate_ext_n),
415
463k
                         den * (1 + p_sys->i_frame_rate_ext_d),
416
463k
                         CLOCK_FREQ );
417
463k
        }
418
419
706k
        if( num && den ) /* fields / den */
420
706k
        {
421
706k
            date_Change( &p_sys->dts, num, den );
422
706k
            date_Change( &p_sys->prev_iframe_dts, num, den );
423
706k
        }
424
706k
    }
425
426
706k
    if( fmt->i_frame_rate != (p_sys->dts.i_divider_num >> 1) ||
427
551k
        fmt->i_frame_rate_base != p_sys->dts.i_divider_den )
428
159k
    {
429
159k
        fmt->i_frame_rate = p_sys->dts.i_divider_num >> 1;
430
159k
        fmt->i_frame_rate_base = p_sys->dts.i_divider_den;
431
432
159k
        msg_Dbg( p_dec, "size %ux%u/%ux%u fps %u:%u",
433
159k
             fmt->i_visible_width, fmt->i_visible_height,
434
159k
             fmt->i_width, fmt->i_height,
435
159k
             fmt->i_frame_rate, fmt->i_frame_rate_base);
436
159k
    }
437
706k
}
438
439
/*****************************************************************************
440
 * OutputFrame: assemble and tag frame
441
 *****************************************************************************/
442
static block_t *OutputFrame( decoder_t *p_dec )
443
706k
{
444
706k
    decoder_sys_t *p_sys = p_dec->p_sys;
445
706k
    block_t *p_pic = NULL;
446
447
706k
    if( !p_sys->p_frame )
448
0
        return NULL;
449
450
706k
    ProcessSequenceParameters( p_dec );
451
452
706k
    p_pic = block_ChainGather( p_sys->p_frame );
453
706k
    if( p_pic == NULL )
454
4
    {
455
4
        p_sys->p_frame = NULL;
456
4
        p_sys->pp_last = &p_sys->p_frame;
457
4
        p_sys->b_frame_slice = false;
458
4
        return p_pic;
459
4
    }
460
461
706k
    unsigned i_num_fields;
462
463
706k
    if( !p_sys->b_seq_progressive && p_sys->i_picture_structure != 0x03 /* Field Picture */ )
464
15.3k
        i_num_fields = 1;
465
691k
    else
466
691k
        i_num_fields = 2;
467
468
706k
    if( p_sys->b_seq_progressive )
469
314k
    {
470
314k
        if( p_sys->i_top_field_first == 0 &&
471
251k
            p_sys->i_repeat_first_field == 1 )
472
3.70k
        {
473
3.70k
            i_num_fields *= 2;
474
3.70k
        }
475
310k
        else if( p_sys->i_top_field_first == 1 &&
476
63.1k
                 p_sys->i_repeat_first_field == 1 )
477
52.6k
        {
478
52.6k
            i_num_fields *= 3;
479
52.6k
        }
480
314k
    }
481
392k
    else
482
392k
    {
483
392k
        if( p_sys->i_picture_structure == 0x03 /* Frame Picture */ )
484
376k
        {
485
376k
            if( p_sys->i_progressive_frame && p_sys->i_repeat_first_field )
486
18.9k
            {
487
18.9k
                i_num_fields += 1;
488
18.9k
            }
489
376k
        }
490
392k
    }
491
492
706k
    switch ( p_sys->i_picture_type )
493
706k
    {
494
34.7k
    case 0x01:
495
34.7k
        p_pic->i_flags |= BLOCK_FLAG_TYPE_I;
496
34.7k
        break;
497
353k
    case 0x02:
498
353k
        p_pic->i_flags |= BLOCK_FLAG_TYPE_P;
499
353k
        break;
500
47.8k
    case 0x03:
501
47.8k
        p_pic->i_flags |= BLOCK_FLAG_TYPE_B;
502
47.8k
        break;
503
706k
    }
504
505
706k
    if( !p_sys->b_seq_progressive )
506
392k
    {
507
392k
        if( p_sys->i_picture_structure < 0x03 )
508
15.3k
        {
509
15.3k
            p_pic->i_flags |= BLOCK_FLAG_SINGLE_FIELD;
510
15.3k
            p_pic->i_flags |= (p_sys->i_picture_structure == 0x01) ? BLOCK_FLAG_TOP_FIELD_FIRST
511
15.3k
                                                                   : BLOCK_FLAG_BOTTOM_FIELD_FIRST;
512
15.3k
        }
513
376k
        else /* if( p_sys->i_picture_structure == 0x03 ) */
514
376k
        {
515
376k
            p_pic->i_flags |= (p_sys->i_top_field_first) ? BLOCK_FLAG_TOP_FIELD_FIRST
516
376k
                                                         : BLOCK_FLAG_BOTTOM_FIELD_FIRST;
517
376k
        }
518
392k
    }
519
520
    /* Special case for DVR-MS where we need to fully build pts from scratch
521
     * and only use first dts as it does not monotonically increase
522
     * This will NOT work with frame repeats and such, as we would need to fully
523
     * fill the DPB to get accurate pts timings. */
524
706k
    if( unlikely( p_dec->fmt_in->i_original_fourcc == VLC_FOURCC( 'D','V','R',' ') ) )
525
0
    {
526
0
        const bool b_first_xmited = (p_sys->i_prev_temporal_ref != p_sys->i_temporal_ref );
527
528
0
        if( ( p_pic->i_flags & BLOCK_FLAG_TYPE_I ) && b_first_xmited )
529
0
        {
530
0
            if( date_Get( &p_sys->prev_iframe_dts ) == VLC_TICK_INVALID )
531
0
            {
532
0
                if( p_sys->i_dts != VLC_TICK_INVALID )
533
0
                {
534
0
                    date_Set( &p_sys->dts, p_sys->i_dts );
535
0
                }
536
0
                else
537
0
                {
538
0
                    if( date_Get( &p_sys->dts ) == VLC_TICK_INVALID )
539
0
                    {
540
0
                        date_Set( &p_sys->dts, VLC_TICK_0 );
541
0
                    }
542
0
                }
543
0
            }
544
0
            p_sys->prev_iframe_dts = p_sys->dts;
545
0
        }
546
547
0
        p_pic->i_dts = date_Get( &p_sys->dts );
548
549
        /* Compute pts from poc */
550
0
        date_t datepts = p_sys->prev_iframe_dts;
551
0
        date_Increment( &datepts, (1 + p_sys->i_temporal_ref) * 2 );
552
553
        /* Field picture second field case */
554
0
        if( p_sys->i_picture_structure != 0x03 )
555
0
        {
556
            /* first sent is not the first in display order */
557
0
            if( (p_sys->i_picture_structure >> 1) != !p_sys->i_top_field_first &&
558
0
                    b_first_xmited )
559
0
            {
560
0
                date_Increment( &datepts, 2 );
561
0
            }
562
0
        }
563
564
0
        p_pic->i_pts = date_Get( &datepts );
565
566
0
        if( date_Get( &p_sys->dts ) != VLC_TICK_INVALID )
567
0
        {
568
0
            date_Increment( &p_sys->dts,  i_num_fields );
569
570
0
            p_pic->i_length = date_Get( &p_sys->dts ) - p_pic->i_dts;
571
0
        }
572
0
        p_sys->i_prev_temporal_ref = p_sys->i_temporal_ref;
573
0
    }
574
706k
    else /* General case, use demuxer's dts/pts when set or interpolate */
575
706k
    {
576
706k
        if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
577
282k
        {
578
            /* Trivial case (DTS == PTS) */
579
            /* Correct interpolated dts when we receive a new pts/dts */
580
282k
            if( p_sys->i_pts != VLC_TICK_INVALID )
581
22.0k
                date_Set( &p_sys->dts, p_sys->i_pts );
582
282k
            if( p_sys->i_dts != VLC_TICK_INVALID )
583
118k
                date_Set( &p_sys->dts, p_sys->i_dts );
584
282k
        }
585
423k
        else
586
423k
        {
587
            /* Correct interpolated dts when we receive a new pts/dts */
588
423k
            if(p_sys->i_last_ref_pts != VLC_TICK_INVALID && !p_sys->b_second_field)
589
51.7k
                date_Set( &p_sys->dts, p_sys->i_last_ref_pts );
590
423k
            if( p_sys->i_dts != VLC_TICK_INVALID )
591
159k
                date_Set( &p_sys->dts, p_sys->i_dts );
592
593
423k
            if( !p_sys->b_second_field )
594
407k
                p_sys->i_last_ref_pts = p_sys->i_pts;
595
423k
        }
596
597
706k
        p_pic->i_dts = date_Get( &p_sys->dts );
598
599
        /* Set PTS only if we have a B frame or if it comes from the stream */
600
706k
        if( p_sys->i_pts != VLC_TICK_INVALID )
601
84.7k
        {
602
84.7k
            p_pic->i_pts = p_sys->i_pts;
603
84.7k
        }
604
621k
        else if( p_sys->i_picture_type == 0x03 )
605
32.7k
        {
606
32.7k
            p_pic->i_pts = p_pic->i_dts;
607
32.7k
        }
608
588k
        else
609
588k
        {
610
588k
            p_pic->i_pts = VLC_TICK_INVALID;
611
588k
        }
612
613
706k
        if( date_Get( &p_sys->dts ) != VLC_TICK_INVALID )
614
672k
        {
615
672k
            date_Increment( &p_sys->dts,  i_num_fields );
616
617
672k
            p_pic->i_length = date_Get( &p_sys->dts ) - p_pic->i_dts;
618
672k
        }
619
706k
    }
620
621
#if 0
622
    msg_Dbg( p_dec, "pic: type=%d struct=%d ref=%d nf=%d tff=%d dts=%"PRId64" ptsdiff=%"PRId64" len=%"PRId64,
623
             p_sys->i_picture_type, p_sys->i_picture_structure, p_sys->i_temporal_ref, i_num_fields,
624
             p_sys->i_top_field_first,
625
             p_pic->i_dts , (p_pic->i_pts != VLC_TICK_INVALID) ? p_pic->i_pts - p_pic->i_dts : 0, p_pic->i_length );
626
#endif
627
628
629
    /* Reset context */
630
706k
    p_sys->p_frame = NULL;
631
706k
    p_sys->pp_last = &p_sys->p_frame;
632
706k
    p_sys->b_frame_slice = false;
633
634
706k
    if( p_sys->i_picture_structure != 0x03 )
635
83.5k
    {
636
83.5k
        p_sys->b_second_field = !p_sys->b_second_field;
637
83.5k
    }
638
622k
    else
639
622k
    {
640
622k
        p_sys->b_second_field = 0;
641
622k
    }
642
643
    /* CC */
644
706k
    p_sys->b_cc_reset = true;
645
706k
    p_sys->i_cc_pts = p_pic->i_pts;
646
706k
    p_sys->i_cc_dts = p_pic->i_dts;
647
706k
    p_sys->i_cc_flags = p_pic->i_flags & BLOCK_FLAG_TYPE_MASK;
648
649
706k
    return p_pic;
650
706k
}
651
652
/*****************************************************************************
653
 * Helpers:
654
 *****************************************************************************/
655
static void PacketizeReset( void *p_private, bool b_flush )
656
49.9k
{
657
49.9k
    VLC_UNUSED(b_flush);
658
49.9k
    decoder_t *p_dec = p_private;
659
49.9k
    decoder_sys_t *p_sys = p_dec->p_sys;
660
661
49.9k
    p_sys->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY;
662
49.9k
    if( p_sys->p_frame )
663
35.9k
    {
664
35.9k
        block_ChainRelease( p_sys->p_frame );
665
35.9k
        p_sys->p_frame = NULL;
666
35.9k
        p_sys->pp_last = &p_sys->p_frame;
667
35.9k
        p_sys->b_frame_slice = false;
668
35.9k
    }
669
49.9k
    date_Set( &p_sys->dts, VLC_TICK_INVALID );
670
49.9k
    date_Set( &p_sys->prev_iframe_dts, VLC_TICK_INVALID );
671
49.9k
    p_sys->i_dts =
672
49.9k
    p_sys->i_pts =
673
49.9k
    p_sys->i_last_ref_pts = VLC_TICK_INVALID;
674
49.9k
    p_sys->b_waiting_iframe = p_sys->b_sync_on_intra_frame;
675
49.9k
    p_sys->i_prev_temporal_ref = 2048;
676
49.9k
}
677
678
static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block )
679
4.68M
{
680
4.68M
    decoder_t *p_dec = p_private;
681
4.68M
    decoder_sys_t *p_sys = p_dec->p_sys;
682
683
    /* Check if we have a picture start code */
684
4.68M
    *pb_ts_used = p_block->p_buffer[3] == PICTURE_STARTCODE;
685
686
4.68M
    p_block = ParseMPEGBlock( p_dec, p_block );
687
4.68M
    if( p_block )
688
685k
    {
689
685k
        p_block->i_flags |= p_sys->i_next_block_flags;
690
685k
        p_sys->i_next_block_flags = 0;
691
685k
    }
692
3.99M
    else *pb_ts_used = false; /* only clear up if output */
693
694
4.68M
    return p_block;
695
4.68M
}
696
697
static block_t * PacketizeDrain( void *p_private )
698
90.0k
{
699
90.0k
    decoder_t *p_dec = p_private;
700
90.0k
    decoder_sys_t *p_sys = p_dec->p_sys;
701
702
90.0k
    if( p_sys->b_waiting_iframe || !p_sys->b_frame_slice )
703
68.9k
        return NULL;
704
705
21.0k
    block_t *p_out = OutputFrame( p_dec );
706
21.0k
    if( p_out )
707
21.0k
    {
708
21.0k
        p_out->i_flags |= p_sys->i_next_block_flags;
709
21.0k
        p_sys->i_next_block_flags = 0;
710
21.0k
    }
711
712
21.0k
    return p_out;
713
90.0k
}
714
715
static int PacketizeValidate( void *p_private, block_t *p_au )
716
706k
{
717
706k
    decoder_t *p_dec = p_private;
718
706k
    decoder_sys_t *p_sys = p_dec->p_sys;
719
720
706k
    if( unlikely( p_sys->b_waiting_iframe ) )
721
0
    {
722
0
        if( (p_au->i_flags & BLOCK_FLAG_TYPE_I) == 0 )
723
0
        {
724
0
            msg_Dbg( p_dec, "waiting on intra frame" );
725
0
            return VLC_EGENERIC;
726
0
        }
727
0
        msg_Dbg( p_dec, "synced on intra frame" );
728
0
        p_sys->b_waiting_iframe = false;
729
0
    }
730
731
    /* We've just started the stream, wait for the first PTS.
732
     * We discard here so we can still get the sequence header. */
733
706k
    if( unlikely( p_sys->i_dts == VLC_TICK_INVALID && p_sys->i_pts == VLC_TICK_INVALID &&
734
706k
        date_Get( &p_sys->dts ) == VLC_TICK_INVALID ))
735
28.8k
    {
736
28.8k
        msg_Dbg( p_dec, "need a starting pts/dts" );
737
28.8k
        return VLC_EGENERIC;
738
28.8k
    }
739
740
    /* When starting the stream we can have the first frame with
741
     * an invalid DTS (i_interpolated_pts is initialized to VLC_TICK_INVALID) */
742
677k
    if( unlikely( p_au->i_dts == VLC_TICK_INVALID ) )
743
4.95k
        p_au->i_dts = p_au->i_pts;
744
745
677k
    return VLC_SUCCESS;
746
706k
}
747
/*****************************************************************************
748
 * ParseMPEGBlock: Re-assemble fragments into a block containing a picture
749
 *****************************************************************************/
750
static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag )
751
4.68M
{
752
4.68M
    decoder_sys_t *p_sys = p_dec->p_sys;
753
4.68M
    block_t *p_pic = NULL;
754
755
4.68M
    const enum mpeg_startcode_e startcode = p_frag->p_buffer[3];
756
    /*
757
     * Check if previous picture is finished
758
     */
759
4.68M
    if( ( p_sys->b_frame_slice &&
760
1.15M
          (startcode == PICTURE_STARTCODE || startcode >  SLICE_STARTCODE_LAST ) ) &&
761
808k
          p_sys->p_seq == NULL )
762
123k
    {
763
        /* We have a picture but without a sequence header we can't
764
         * do anything */
765
123k
        msg_Dbg( p_dec, "waiting for sequence start" );
766
123k
        if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
767
123k
        p_sys->p_frame = NULL;
768
123k
        p_sys->pp_last = &p_sys->p_frame;
769
123k
        p_sys->b_frame_slice = false;
770
771
123k
    }
772
4.55M
    else if( p_sys->b_frame_slice &&
773
1.02M
             (startcode == PICTURE_STARTCODE || startcode >  SLICE_STARTCODE_LAST) )
774
685k
    {
775
685k
        const bool b_eos = startcode == SEQUENCE_END_STARTCODE;
776
777
685k
        if( b_eos )
778
175k
        {
779
175k
            block_ChainLastAppend( &p_sys->pp_last, p_frag );
780
175k
            p_frag = NULL;
781
175k
        }
782
783
685k
        p_pic = OutputFrame( p_dec );
784
785
685k
        if( p_pic && b_eos )
786
175k
            p_pic->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
787
685k
    }
788
789
4.68M
    if( !p_pic && p_sys->b_cc_reset )
790
693k
    {
791
693k
        p_sys->b_cc_reset = false;
792
693k
        cc_Flush( &p_sys->cc );
793
693k
    }
794
795
4.68M
    if( !p_frag )
796
175k
        return p_pic;
797
    /*
798
     * Check info of current fragment
799
     */
800
4.50M
    if( startcode == GROUP_STARTCODE )
801
608k
    {
802
        /* Group start code */
803
608k
        unsigned i_fps = p_sys->dts.i_divider_num / (p_sys->dts.i_divider_den << 1);
804
608k
        if( p_sys->p_seq && p_sys->i_seq_old > i_fps )
805
198k
        {
806
            /* Useful for mpeg1: repeat sequence header every second */
807
198k
            const block_t * params[2] = { p_sys->p_seq, p_sys->p_ext };
808
496k
            for( int i=0; i<2; i++ )
809
397k
            {
810
397k
                if( params[i] == NULL )
811
99.8k
                    break;
812
297k
                block_t *p_dup = block_Duplicate( params[i] );
813
297k
                if( p_dup )
814
297k
                    block_ChainLastAppend( &p_sys->pp_last, p_dup );
815
297k
            }
816
198k
            p_sys->i_seq_old = 0;
817
198k
        }
818
608k
    }
819
3.89M
    else if( startcode == SEQUENCE_HEADER_STARTCODE && p_frag->i_buffer >= 11 )
820
370k
    {
821
        /* Sequence header code */
822
370k
        if( p_sys->p_seq ) block_Release( p_sys->p_seq );
823
370k
        if( p_sys->p_ext ) block_Release( p_sys->p_ext );
824
825
370k
        p_sys->p_seq = block_Duplicate( p_frag );
826
370k
        p_sys->i_seq_old = 0;
827
370k
        p_sys->p_ext = NULL;
828
829
370k
        p_sys->i_h_size_value = ( p_frag->p_buffer[4] << 4)|(p_frag->p_buffer[5] >> 4 );
830
370k
        p_sys->i_v_size_value = ( (p_frag->p_buffer[5]&0x0f) << 8 )|p_frag->p_buffer[6];
831
370k
        p_sys->i_aspect_ratio_info = p_frag->p_buffer[7] >> 4;
832
833
        /* TODO: MPEG1 aspect ratio */
834
835
370k
        p_sys->i_frame_rate_value = p_frag->p_buffer[7] & 0x0f;
836
837
370k
        p_sys->i_bitratelower18 = (p_frag->p_buffer[ 8] << 12) |
838
370k
                                  (p_frag->p_buffer[ 9] <<  4) |
839
370k
                                  (p_frag->p_buffer[10] & 0x0F);
840
370k
    }
841
3.52M
    else if( startcode == EXTENSION_STARTCODE && p_frag->i_buffer > 4 )
842
211k
    {
843
        /* extension_start_code_identifier */
844
211k
        const enum extension_start_code_identifier_e extid = p_frag->p_buffer[4] >> 4;
845
846
        /* Extension start code */
847
211k
        if( extid == SEQUENCE_EXTENSION_ID )
848
161k
        {
849
#if 0
850
            static const int mpeg2_aspect[16][2] =
851
            {
852
                {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
853
                {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1}, {0,1},
854
                {0,1}, {0,1}
855
            };
856
#endif
857
            /* sequence extension */
858
161k
            if( p_sys->p_ext) block_Release( p_sys->p_ext );
859
161k
            p_sys->p_ext = block_Duplicate( p_frag );
860
861
161k
            if( p_frag->i_buffer >= 10 )
862
143k
            {
863
                /* profile and level indication */
864
143k
                if( p_dec->fmt_out.i_profile == -1 )
865
53.7k
                {
866
53.7k
                    const uint16_t profilelevel = ((p_frag->p_buffer[4] << 4) |
867
53.7k
                                                   (p_frag->p_buffer[5] >> 4)) & 0xFF;
868
53.7k
                    int i_profile = -1;
869
53.7k
                    int i_level = -1;
870
53.7k
                    switch( profilelevel )
871
53.7k
                    {
872
5
                        case 0x82:
873
5
                            i_profile = PROFILE_MPEG2_422;
874
5
                            i_level = LEVEL_MPEG2_HIGH;
875
5
                            break;
876
8
                        case 0x85:
877
8
                            i_profile = PROFILE_MPEG2_422;
878
8
                            i_level = LEVEL_MPEG2_MAIN;
879
8
                            break;
880
12
                        case 0x8A:
881
12
                            i_profile = PROFILE_MPEG2_MULTIVIEW;
882
12
                            i_level = LEVEL_MPEG2_HIGH;
883
12
                            break;
884
17
                        case 0x8B:
885
17
                            i_profile = PROFILE_MPEG2_MULTIVIEW;
886
17
                            i_level = LEVEL_MPEG2_HIGH_1440;
887
17
                            break;
888
186
                        case 0x8D:
889
186
                            i_profile = PROFILE_MPEG2_MULTIVIEW;
890
186
                            i_level = LEVEL_MPEG2_MAIN;
891
186
                            break;
892
21
                        case 0x8E:
893
21
                            i_profile = PROFILE_MPEG2_MULTIVIEW;
894
21
                            i_level = LEVEL_MPEG2_LOW;
895
21
                            break;
896
53.4k
                        default:
897
53.4k
                            if( (profilelevel & 0x80) == 0 ) /* escape bit */
898
2.70k
                            {
899
2.70k
                                i_profile = (profilelevel >> 4) & 0x07;
900
2.70k
                                i_level = profilelevel & 0x0F;
901
2.70k
                            }
902
53.4k
                            break;
903
53.7k
                    }
904
53.7k
                    p_dec->fmt_out.i_profile = i_profile;
905
53.7k
                    p_dec->fmt_out.i_level = i_level;
906
53.7k
                }
907
908
143k
                p_sys->b_seq_progressive =
909
143k
                    p_frag->p_buffer[5]&0x08 ? true : false;
910
911
143k
                p_sys->i_h_size_ext = ((p_frag->p_buffer[5] & 0x01) << 1) | (p_frag->p_buffer[6] >> 7);
912
143k
                p_sys->i_v_size_ext = (p_frag->p_buffer[6] >> 5) & 0x03;
913
914
143k
                p_sys->i_bitrateupper12 = ((p_frag->p_buffer[6] & 0x1F) << 8) | (p_frag->p_buffer[7] >> 1);
915
916
143k
                p_sys->b_low_delay =
917
143k
                    p_frag->p_buffer[9]&0x80 ? true : false;
918
919
143k
                p_sys->i_frame_rate_ext_n = (p_frag->p_buffer[9] >> 5) & 0x03;
920
143k
                p_sys->i_frame_rate_ext_d = p_frag->p_buffer[9] & 0x1F;
921
143k
            }
922
923
            /* Do not set aspect ratio : in case we're transcoding,
924
             * transcode will take our fmt_out as a fmt_in to libmpeg2.
925
             * libmpeg2.c will then believe that the user has requested
926
             * a specific aspect ratio, which she hasn't. Thus in case
927
             * of aspect ratio change, we're screwed. --Meuuh
928
             */
929
#if 0
930
            p_dec->fmt_out.video.i_sar_num =
931
                mpeg2_aspect[p_sys->i_aspect_ratio_info][0] *
932
                p_dec->fmt_out.video.i_height;
933
            p_dec->fmt_out.video.i_sar_den =
934
                mpeg2_aspect[p_sys->i_aspect_ratio_info][1] *
935
                p_dec->fmt_out.video.i_width;
936
#endif
937
938
161k
        }
939
50.1k
        else if( extid == PICTURE_CODING_EXTENSION_ID && p_frag->i_buffer > 8 )
940
8.32k
        {
941
            /* picture extension */
942
8.32k
            p_sys->i_picture_structure = p_frag->p_buffer[6]&0x03;
943
8.32k
            p_sys->i_top_field_first   = p_frag->p_buffer[7] >> 7;
944
8.32k
            p_sys->i_repeat_first_field= (p_frag->p_buffer[7]>>1)&0x01;
945
8.32k
            p_sys->i_progressive_frame = p_frag->p_buffer[8] >> 7;
946
8.32k
        }
947
41.8k
        else if( extid == SEQUENCE_DISPLAY_EXTENSION_ID && p_frag->i_buffer > 8 )
948
26.3k
        {
949
            /* Sequence display extension */
950
26.3k
            bool contains_color_description = (p_frag->p_buffer[4] & 0x01);
951
            //uint8_t video_format = (p_frag->p_buffer[4] & 0x0f) >> 1;
952
26.3k
            if( contains_color_description && p_frag->i_buffer > 11 )
953
20.6k
            {
954
20.6k
                h26x_colour_description_t colour;
955
20.6k
                colour.colour_primaries = p_frag->p_buffer[5];
956
20.6k
                colour.transfer_characteristics = p_frag->p_buffer[6];
957
20.6k
                colour.matrix_coeffs = p_frag->p_buffer[7];
958
20.6k
                colour.full_range_flag = 0;
959
20.6k
                video_color_range_t range;
960
20.6k
                h26x_get_colorimetry( &colour,
961
20.6k
                                      &p_dec->fmt_out.video.primaries,
962
20.6k
                                      &p_dec->fmt_out.video.transfer,
963
20.6k
                                      &p_dec->fmt_out.video.space,
964
20.6k
                                      &range );
965
20.6k
            }
966
26.3k
        }
967
211k
    }
968
3.31M
    else if( startcode == USER_DATA_STARTCODE && p_frag->i_buffer > 8 )
969
412k
    {
970
        /* Frame Packing extension identifier as H262 2012 Amd4 Annex L */
971
412k
        if( !memcmp( &p_frag->p_buffer[4], "JP3D", 4 ) &&
972
7.19k
            p_frag->i_buffer > 11 && p_frag->p_buffer[8] == 0x03 &&
973
1.82k
            p_dec->fmt_in->video.multiview_mode == MULTIVIEW_2D )
974
1.82k
        {
975
1.82k
            video_multiview_mode_t mode;
976
1.82k
            switch( p_frag->p_buffer[9] & 0x7F )
977
1.82k
            {
978
70
                case 0x03:
979
70
                    mode = MULTIVIEW_STEREO_SBS; break;
980
482
                case 0x04:
981
482
                    mode = MULTIVIEW_STEREO_TB; break;
982
137
                case 0x08:
983
1.27k
                default:
984
1.27k
                    mode = MULTIVIEW_2D; break;
985
1.82k
            }
986
1.82k
            p_dec->fmt_out.video.multiview_mode = mode;
987
1.82k
        }
988
410k
        else
989
410k
        cc_ProbeAndExtract( &p_sys->cc, p_sys->i_top_field_first,
990
410k
                    &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
991
412k
    }
992
2.90M
    else if( startcode == PICTURE_STARTCODE )
993
1.22M
    {
994
        /* Picture start code */
995
1.22M
        p_sys->i_seq_old++;
996
997
1.22M
        if( p_frag->i_buffer >= 6 )
998
971k
        {
999
971k
            p_sys->i_temporal_ref =
1000
971k
                ( p_frag->p_buffer[4] << 2 )|(p_frag->p_buffer[5] >> 6);
1001
971k
            p_sys->i_picture_type = ( p_frag->p_buffer[5] >> 3 ) & 0x03;
1002
971k
        }
1003
1004
        /* Check if we can use timestamps */
1005
1.22M
        if(p_frag->i_dts != VLC_TICK_INVALID &&
1006
630k
           p_frag->i_dts <= p_sys->i_dts)
1007
253k
        {
1008
253k
            date_t next = p_sys->dts;
1009
253k
            date_Set(&next, p_frag->i_dts);
1010
            /* Because the prev timestamp could have been repeated though
1011
             * helper, clear up if we are within 2 frames backward */
1012
253k
            if(date_Increment(&next, 4) >= p_sys->i_dts)
1013
230k
                p_frag->i_dts = p_frag->i_pts = VLC_TICK_INVALID; /* do not reuse */
1014
253k
        }
1015
1016
1.22M
        p_sys->i_dts = p_frag->i_dts;
1017
1.22M
        p_sys->i_pts = p_frag->i_pts;
1018
1.22M
    }
1019
1.68M
    else if( startcode >= SLICE_STARTCODE_FIRST &&
1020
1.68M
             startcode <= SLICE_STARTCODE_LAST )
1021
1.18M
    {
1022
        /* Slice start code */
1023
1.18M
        p_sys->b_frame_slice = true;
1024
1.18M
    }
1025
1026
    /* Append the block */
1027
4.50M
    block_ChainLastAppend( &p_sys->pp_last, p_frag );
1028
1029
4.50M
    return p_pic;
1030
4.50M
}