Coverage Report

Created: 2025-12-14 06:40

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