Coverage Report

Created: 2026-11-12 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/packetizer/startcode_helper.h
Line
Count
Source
1
/*****************************************************************************
2
 * startcode_helper.h: Startcodes helpers
3
 *****************************************************************************
4
 * Copyright (C) 2016 VideoLAN Authors
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this program; if not, write to the Free Software Foundation,
18
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19
 *****************************************************************************/
20
#ifndef VLC_STARTCODE_HELPER_H_
21
#define VLC_STARTCODE_HELPER_H_
22
23
#include <vlc_cpu.h>
24
25
#ifdef CAN_COMPILE_SSE2
26
#  if defined __has_attribute
27
#    if __has_attribute(__vector_size__)
28
#      define HAS_ATTRIBUTE_VECTORSIZE
29
#    endif
30
#  endif
31
32
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
33
    typedef unsigned char v16qu __attribute__((__vector_size__(16)));
34
#  endif
35
#endif
36
37
/* Looks up efficiently for an AnnexB startcode 0x00 0x00 0x01
38
 * by using a 4 times faster trick than single byte lookup. */
39
40
2.16G
#define TRY_MATCH(p,a) {\
41
2.16G
     if (p[a+1] == 0) {\
42
1.35G
            if (p[a+0] == 0 && p[a+2] == 1)\
43
1.35G
                return a+p;\
44
1.35G
            if (p[a+2] == 0 && p[a+3] == 1)\
45
1.34G
                return a+p+1;\
46
1.34G
        }\
47
2.16G
        if (p[a+3] == 0) {\
48
1.29G
            if (p[a+2] == 0 && p[a+4] == 1)\
49
1.29G
                return a+p+2;\
50
1.29G
            if (p[a+4] == 0 && p[a+5] == 1)\
51
1.29G
                return a+p+3;\
52
1.29G
        }\
53
2.15G
    }
54
55
#ifdef CAN_COMPILE_SSE2
56
57
__attribute__ ((__target__ ("sse2")))
58
static inline const uint8_t * startcode_FindAnnexB_SSE2( const uint8_t *p, const uint8_t *end )
59
85.9M
{
60
    /* First align to 16 */
61
    /* Skipping this step and doing unaligned loads isn't faster */
62
85.9M
    const uint8_t *alignedend = p + 16 - ((intptr_t)p & 15);
63
667M
    for (end -= 3; p < alignedend && p <= end; p++) {
64
613M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
65
31.2M
            return p;
66
613M
    }
67
68
54.7M
    if( p == end )
69
126k
        return NULL;
70
71
54.6M
    alignedend = end - ((intptr_t) end & 15);
72
54.6M
    if( alignedend > p )
73
37.3M
    {
74
37.3M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
75
37.3M
        const v16qu zeros = { 0 };
76
37.3M
#  endif
77
78
2.10G
        for( ; p < alignedend; p += 16)
79
2.07G
        {
80
2.07G
            uint32_t match;
81
2.07G
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
82
2.07G
            asm volatile(
83
2.07G
                "movdqa   0(%[v]),   %%xmm0\n"
84
2.07G
                "pcmpeqb %[czero],   %%xmm0\n"
85
2.07G
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
86
2.07G
                : [match]"=r"(match)
87
2.07G
                : [v]"r"(p), [czero]"x"(zeros)
88
2.07G
                : "xmm0"
89
2.07G
            );
90
#  else
91
            asm volatile(
92
                "movdqa   0(%[v]),   %%xmm0\n"
93
                "pxor      %%xmm1,   %%xmm1\n"
94
                "pcmpeqb   %%xmm1,   %%xmm0\n"
95
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
96
                : [match]"=r"(match)
97
                : [v]"r"(p)
98
                : "xmm0", "xmm1"
99
            );
100
#  endif
101
2.07G
            if( match & 0x000F )
102
2.07G
                TRY_MATCH(p, 0);
103
2.07G
            if( match & 0x00F0 )
104
2.06G
                TRY_MATCH(p, 4);
105
2.06G
            if( match & 0x0F00 )
106
2.06G
                TRY_MATCH(p, 8);
107
2.06G
            if( match & 0xF000 )
108
2.06G
                TRY_MATCH(p, 12);
109
2.06G
        }
110
37.3M
    }
111
112
396M
    for (; p <= end; p++) {
113
350M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
114
262k
            return p;
115
350M
    }
116
117
46.5M
    return NULL;
118
46.8M
}
h264.c:startcode_FindAnnexB_SSE2
Line
Count
Source
59
6.91M
{
60
    /* First align to 16 */
61
    /* Skipping this step and doing unaligned loads isn't faster */
62
6.91M
    const uint8_t *alignedend = p + 16 - ((intptr_t)p & 15);
63
64.6M
    for (end -= 3; p < alignedend && p <= end; p++) {
64
59.8M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
65
2.14M
            return p;
66
59.8M
    }
67
68
4.76M
    if( p == end )
69
77.4k
        return NULL;
70
71
4.69M
    alignedend = end - ((intptr_t) end & 15);
72
4.69M
    if( alignedend > p )
73
4.37M
    {
74
4.37M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
75
4.37M
        const v16qu zeros = { 0 };
76
4.37M
#  endif
77
78
310M
        for( ; p < alignedend; p += 16)
79
307M
        {
80
307M
            uint32_t match;
81
307M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
82
307M
            asm volatile(
83
307M
                "movdqa   0(%[v]),   %%xmm0\n"
84
307M
                "pcmpeqb %[czero],   %%xmm0\n"
85
307M
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
86
307M
                : [match]"=r"(match)
87
307M
                : [v]"r"(p), [czero]"x"(zeros)
88
307M
                : "xmm0"
89
307M
            );
90
#  else
91
            asm volatile(
92
                "movdqa   0(%[v]),   %%xmm0\n"
93
                "pxor      %%xmm1,   %%xmm1\n"
94
                "pcmpeqb   %%xmm1,   %%xmm0\n"
95
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
96
                : [match]"=r"(match)
97
                : [v]"r"(p)
98
                : "xmm0", "xmm1"
99
            );
100
#  endif
101
307M
            if( match & 0x000F )
102
307M
                TRY_MATCH(p, 0);
103
307M
            if( match & 0x00F0 )
104
307M
                TRY_MATCH(p, 4);
105
307M
            if( match & 0x0F00 )
106
306M
                TRY_MATCH(p, 8);
107
306M
            if( match & 0xF000 )
108
306M
                TRY_MATCH(p, 12);
109
306M
        }
110
4.37M
    }
111
112
43.1M
    for (; p <= end; p++) {
113
39.8M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
114
25.8k
            return p;
115
39.8M
    }
116
117
3.33M
    return NULL;
118
3.35M
}
Unexecuted instantiation: hxxx_sei.c:startcode_FindAnnexB_SSE2
Unexecuted instantiation: h264_nal.c:startcode_FindAnnexB_SSE2
Unexecuted instantiation: h264_slice.c:startcode_FindAnnexB_SSE2
hevc.c:startcode_FindAnnexB_SSE2
Line
Count
Source
59
28.0M
{
60
    /* First align to 16 */
61
    /* Skipping this step and doing unaligned loads isn't faster */
62
28.0M
    const uint8_t *alignedend = p + 16 - ((intptr_t)p & 15);
63
132M
    for (end -= 3; p < alignedend && p <= end; p++) {
64
121M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
65
17.4M
            return p;
66
121M
    }
67
68
10.5M
    if( p == end )
69
5.31k
        return NULL;
70
71
10.5M
    alignedend = end - ((intptr_t) end & 15);
72
10.5M
    if( alignedend > p )
73
7.10M
    {
74
7.10M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
75
7.10M
        const v16qu zeros = { 0 };
76
7.10M
#  endif
77
78
475M
        for( ; p < alignedend; p += 16)
79
471M
        {
80
471M
            uint32_t match;
81
471M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
82
471M
            asm volatile(
83
471M
                "movdqa   0(%[v]),   %%xmm0\n"
84
471M
                "pcmpeqb %[czero],   %%xmm0\n"
85
471M
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
86
471M
                : [match]"=r"(match)
87
471M
                : [v]"r"(p), [czero]"x"(zeros)
88
471M
                : "xmm0"
89
471M
            );
90
#  else
91
            asm volatile(
92
                "movdqa   0(%[v]),   %%xmm0\n"
93
                "pxor      %%xmm1,   %%xmm1\n"
94
                "pcmpeqb   %%xmm1,   %%xmm0\n"
95
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
96
                : [match]"=r"(match)
97
                : [v]"r"(p)
98
                : "xmm0", "xmm1"
99
            );
100
#  endif
101
471M
            if( match & 0x000F )
102
469M
                TRY_MATCH(p, 0);
103
469M
            if( match & 0x00F0 )
104
469M
                TRY_MATCH(p, 4);
105
469M
            if( match & 0x0F00 )
106
468M
                TRY_MATCH(p, 8);
107
468M
            if( match & 0xF000 )
108
468M
                TRY_MATCH(p, 12);
109
468M
        }
110
7.10M
    }
111
112
62.0M
    for (; p <= end; p++) {
113
54.6M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
114
38.5k
            return p;
115
54.6M
    }
116
117
7.38M
    return NULL;
118
7.41M
}
Unexecuted instantiation: hevc_nal.c:startcode_FindAnnexB_SSE2
mpeg4video.c:startcode_FindAnnexB_SSE2
Line
Count
Source
59
3.11M
{
60
    /* First align to 16 */
61
    /* Skipping this step and doing unaligned loads isn't faster */
62
3.11M
    const uint8_t *alignedend = p + 16 - ((intptr_t)p & 15);
63
20.1M
    for (end -= 3; p < alignedend && p <= end; p++) {
64
17.7M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
65
699k
            return p;
66
17.7M
    }
67
68
2.41M
    if( p == end )
69
1.23k
        return NULL;
70
71
2.40M
    alignedend = end - ((intptr_t) end & 15);
72
2.40M
    if( alignedend > p )
73
917k
    {
74
917k
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
75
917k
        const v16qu zeros = { 0 };
76
917k
#  endif
77
78
5.32M
        for( ; p < alignedend; p += 16)
79
4.90M
        {
80
4.90M
            uint32_t match;
81
4.90M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
82
4.90M
            asm volatile(
83
4.90M
                "movdqa   0(%[v]),   %%xmm0\n"
84
4.90M
                "pcmpeqb %[czero],   %%xmm0\n"
85
4.90M
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
86
4.90M
                : [match]"=r"(match)
87
4.90M
                : [v]"r"(p), [czero]"x"(zeros)
88
4.90M
                : "xmm0"
89
4.90M
            );
90
#  else
91
            asm volatile(
92
                "movdqa   0(%[v]),   %%xmm0\n"
93
                "pxor      %%xmm1,   %%xmm1\n"
94
                "pcmpeqb   %%xmm1,   %%xmm0\n"
95
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
96
                : [match]"=r"(match)
97
                : [v]"r"(p)
98
                : "xmm0", "xmm1"
99
            );
100
#  endif
101
4.90M
            if( match & 0x000F )
102
4.75M
                TRY_MATCH(p, 0);
103
4.75M
            if( match & 0x00F0 )
104
4.62M
                TRY_MATCH(p, 4);
105
4.62M
            if( match & 0x0F00 )
106
4.50M
                TRY_MATCH(p, 8);
107
4.50M
            if( match & 0xF000 )
108
4.41M
                TRY_MATCH(p, 12);
109
4.41M
        }
110
917k
    }
111
112
7.61M
    for (; p <= end; p++) {
113
5.70M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
114
8.28k
            return p;
115
5.70M
    }
116
117
1.90M
    return NULL;
118
1.91M
}
mpegvideo.c:startcode_FindAnnexB_SSE2
Line
Count
Source
59
41.6M
{
60
    /* First align to 16 */
61
    /* Skipping this step and doing unaligned loads isn't faster */
62
41.6M
    const uint8_t *alignedend = p + 16 - ((intptr_t)p & 15);
63
413M
    for (end -= 3; p < alignedend && p <= end; p++) {
64
379M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
65
7.18M
            return p;
66
379M
    }
67
68
34.4M
    if( p == end )
69
22.5k
        return NULL;
70
71
34.4M
    alignedend = end - ((intptr_t) end & 15);
72
34.4M
    if( alignedend > p )
73
22.8M
    {
74
22.8M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
75
22.8M
        const v16qu zeros = { 0 };
76
22.8M
#  endif
77
78
1.00G
        for( ; p < alignedend; p += 16)
79
988M
        {
80
988M
            uint32_t match;
81
988M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
82
988M
            asm volatile(
83
988M
                "movdqa   0(%[v]),   %%xmm0\n"
84
988M
                "pcmpeqb %[czero],   %%xmm0\n"
85
988M
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
86
988M
                : [match]"=r"(match)
87
988M
                : [v]"r"(p), [czero]"x"(zeros)
88
988M
                : "xmm0"
89
988M
            );
90
#  else
91
            asm volatile(
92
                "movdqa   0(%[v]),   %%xmm0\n"
93
                "pxor      %%xmm1,   %%xmm1\n"
94
                "pcmpeqb   %%xmm1,   %%xmm0\n"
95
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
96
                : [match]"=r"(match)
97
                : [v]"r"(p)
98
                : "xmm0", "xmm1"
99
            );
100
#  endif
101
988M
            if( match & 0x000F )
102
987M
                TRY_MATCH(p, 0);
103
987M
            if( match & 0x00F0 )
104
987M
                TRY_MATCH(p, 4);
105
987M
            if( match & 0x0F00 )
106
986M
                TRY_MATCH(p, 8);
107
986M
            if( match & 0xF000 )
108
986M
                TRY_MATCH(p, 12);
109
986M
        }
110
22.8M
    }
111
112
264M
    for (; p <= end; p++) {
113
231M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
114
124k
            return p;
115
231M
    }
116
117
32.3M
    return NULL;
118
32.4M
}
vc1.c:startcode_FindAnnexB_SSE2
Line
Count
Source
59
6.21M
{
60
    /* First align to 16 */
61
    /* Skipping this step and doing unaligned loads isn't faster */
62
6.21M
    const uint8_t *alignedend = p + 16 - ((intptr_t)p & 15);
63
37.3M
    for (end -= 3; p < alignedend && p <= end; p++) {
64
34.8M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
65
3.71M
            return p;
66
34.8M
    }
67
68
2.50M
    if( p == end )
69
20.3k
        return NULL;
70
71
2.48M
    alignedend = end - ((intptr_t) end & 15);
72
2.48M
    if( alignedend > p )
73
2.10M
    {
74
2.10M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
75
2.10M
        const v16qu zeros = { 0 };
76
2.10M
#  endif
77
78
301M
        for( ; p < alignedend; p += 16)
79
300M
        {
80
300M
            uint32_t match;
81
300M
#  ifdef HAS_ATTRIBUTE_VECTORSIZE
82
300M
            asm volatile(
83
300M
                "movdqa   0(%[v]),   %%xmm0\n"
84
300M
                "pcmpeqb %[czero],   %%xmm0\n"
85
300M
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
86
300M
                : [match]"=r"(match)
87
300M
                : [v]"r"(p), [czero]"x"(zeros)
88
300M
                : "xmm0"
89
300M
            );
90
#  else
91
            asm volatile(
92
                "movdqa   0(%[v]),   %%xmm0\n"
93
                "pxor      %%xmm1,   %%xmm1\n"
94
                "pcmpeqb   %%xmm1,   %%xmm0\n"
95
                "pmovmskb  %%xmm0,   %[match]\n" /* mask will be in reversed match order */
96
                : [match]"=r"(match)
97
                : [v]"r"(p)
98
                : "xmm0", "xmm1"
99
            );
100
#  endif
101
300M
            if( match & 0x000F )
102
300M
                TRY_MATCH(p, 0);
103
300M
            if( match & 0x00F0 )
104
299M
                TRY_MATCH(p, 4);
105
299M
            if( match & 0x0F00 )
106
299M
                TRY_MATCH(p, 8);
107
299M
            if( match & 0xF000 )
108
299M
                TRY_MATCH(p, 12);
109
299M
        }
110
2.10M
    }
111
112
19.5M
    for (; p <= end; p++) {
113
17.8M
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
114
65.6k
            return p;
115
17.8M
    }
116
117
1.66M
    return NULL;
118
1.72M
}
119
120
#endif
121
122
/* That code is adapted from libav's ff_avc_find_startcode_internal
123
 * and i believe the trick originated from
124
 * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
125
 */
126
static inline const uint8_t * startcode_FindAnnexB_Bits( const uint8_t *p, const uint8_t *end )
127
0
{
128
0
    const uint8_t *a = p + 4 - ((intptr_t)p & 3);
129
130
0
    for (end -= 3; p < a && p <= end; p++) {
131
0
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
132
0
            return p;
133
0
    }
134
135
0
    for (end -= 3; p < end; p += 4) {
136
0
        uint32_t x;
137
0
        memcpy(&x, p, sizeof(x));
138
0
        if ((x - 0x01010101) & (~x) & 0x80808080)
139
0
        {
140
            /* matching DW isn't faster */
141
0
            TRY_MATCH(p, 0);
142
0
        }
143
0
    }
144
145
0
    for (end += 3; p <= end; p++) {
146
0
        if (p[0] == 0 && p[1] == 0 && p[2] == 1)
147
0
            return p;
148
0
    }
149
150
0
    return NULL;
151
0
}
Unexecuted instantiation: h264.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: hxxx_sei.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: h264_nal.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: h264_slice.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: hevc.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: hevc_nal.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: mpeg4video.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: mpegvideo.c:startcode_FindAnnexB_Bits
Unexecuted instantiation: vc1.c:startcode_FindAnnexB_Bits
152
#undef TRY_MATCH
153
154
#ifdef CAN_COMPILE_SSE2
155
static inline const uint8_t * startcode_FindAnnexB( const uint8_t *p, const uint8_t *end )
156
85.9M
{
157
85.9M
    if (vlc_CPU_SSE2())
158
85.9M
        return startcode_FindAnnexB_SSE2(p, end);
159
0
    else
160
0
        return startcode_FindAnnexB_Bits(p, end);
161
85.9M
}
h264.c:startcode_FindAnnexB
Line
Count
Source
156
6.91M
{
157
6.91M
    if (vlc_CPU_SSE2())
158
6.91M
        return startcode_FindAnnexB_SSE2(p, end);
159
0
    else
160
0
        return startcode_FindAnnexB_Bits(p, end);
161
6.91M
}
Unexecuted instantiation: hxxx_sei.c:startcode_FindAnnexB
Unexecuted instantiation: h264_nal.c:startcode_FindAnnexB
Unexecuted instantiation: h264_slice.c:startcode_FindAnnexB
hevc.c:startcode_FindAnnexB
Line
Count
Source
156
28.0M
{
157
28.0M
    if (vlc_CPU_SSE2())
158
28.0M
        return startcode_FindAnnexB_SSE2(p, end);
159
0
    else
160
0
        return startcode_FindAnnexB_Bits(p, end);
161
28.0M
}
Unexecuted instantiation: hevc_nal.c:startcode_FindAnnexB
mpeg4video.c:startcode_FindAnnexB
Line
Count
Source
156
3.11M
{
157
3.11M
    if (vlc_CPU_SSE2())
158
3.11M
        return startcode_FindAnnexB_SSE2(p, end);
159
0
    else
160
0
        return startcode_FindAnnexB_Bits(p, end);
161
3.11M
}
mpegvideo.c:startcode_FindAnnexB
Line
Count
Source
156
41.6M
{
157
41.6M
    if (vlc_CPU_SSE2())
158
41.6M
        return startcode_FindAnnexB_SSE2(p, end);
159
0
    else
160
0
        return startcode_FindAnnexB_Bits(p, end);
161
41.6M
}
vc1.c:startcode_FindAnnexB
Line
Count
Source
156
6.21M
{
157
6.21M
    if (vlc_CPU_SSE2())
158
6.21M
        return startcode_FindAnnexB_SSE2(p, end);
159
0
    else
160
0
        return startcode_FindAnnexB_Bits(p, end);
161
6.21M
}
162
#else
163
    #define startcode_FindAnnexB startcode_FindAnnexB_Bits
164
#endif
165
166
#endif