FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/nal.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 82 96 85.4%
Functions: 8 9 88.9%
Branches: 72 86 83.7%

Line Branch Exec Source
1 /*
2 * NAL helper functions for muxers
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <stdint.h>
22 #include <string.h>
23
24 #include "libavutil/mem.h"
25 #include "libavutil/error.h"
26 #include "libavcodec/defs.h"
27 #include "avio.h"
28 #include "avio_internal.h"
29 #include "nal.h"
30
31 2581 static const uint8_t *nal_find_startcode_internal(const uint8_t *p, const uint8_t *end)
32 {
33 2581 const uint8_t *a = p + 4 - ((intptr_t)p & 3);
34
35
4/4
✓ Branch 0 taken 7380 times.
✓ Branch 1 taken 1802 times.
✓ Branch 2 taken 7379 times.
✓ Branch 3 taken 1 times.
9182 for (end -= 3; p < a && p < end; p++) {
36
6/6
✓ Branch 0 taken 1813 times.
✓ Branch 1 taken 5566 times.
✓ Branch 2 taken 1551 times.
✓ Branch 3 taken 262 times.
✓ Branch 4 taken 778 times.
✓ Branch 5 taken 773 times.
7379 if (p[0] == 0 && p[1] == 0 && p[2] == 1)
37 778 return p;
38 }
39
40
2/2
✓ Branch 0 taken 559968 times.
✓ Branch 1 taken 738 times.
560706 for (end -= 3; p < end; p += 4) {
41 559968 uint32_t x = *(const uint32_t*)p;
42 // if ((x - 0x01000100) & (~x) & 0x80008000) // little endian
43 // if ((x - 0x00010001) & (~x) & 0x00800080) // big endian
44
2/2
✓ Branch 0 taken 7621 times.
✓ Branch 1 taken 552347 times.
559968 if ((x - 0x01010101) & (~x) & 0x80808080) { // generic
45
2/2
✓ Branch 0 taken 2394 times.
✓ Branch 1 taken 5227 times.
7621 if (p[1] == 0) {
46
4/4
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 2023 times.
✓ Branch 2 taken 237 times.
✓ Branch 3 taken 134 times.
2394 if (p[0] == 0 && p[2] == 1)
47 237 return p;
48
4/4
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 1557 times.
✓ Branch 2 taken 392 times.
✓ Branch 3 taken 208 times.
2157 if (p[2] == 0 && p[3] == 1)
49 392 return p+1;
50 }
51
2/2
✓ Branch 0 taken 2273 times.
✓ Branch 1 taken 4719 times.
6992 if (p[3] == 0) {
52
4/4
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 1930 times.
✓ Branch 2 taken 219 times.
✓ Branch 3 taken 124 times.
2273 if (p[2] == 0 && p[4] == 1)
53 219 return p+2;
54
4/4
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 1680 times.
✓ Branch 2 taken 217 times.
✓ Branch 3 taken 157 times.
2054 if (p[4] == 0 && p[5] == 1)
55 217 return p+3;
56 }
57 }
58 }
59
60
2/2
✓ Branch 0 taken 1115 times.
✓ Branch 1 taken 738 times.
1853 for (end += 3; p < end; p++) {
61
3/6
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1061 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1115 if (p[0] == 0 && p[1] == 0 && p[2] == 1)
62 return p;
63 }
64
65 738 return end + 3;
66 }
67
68 2581 const uint8_t *ff_nal_find_startcode(const uint8_t *p, const uint8_t *end){
69 2581 const uint8_t *out = nal_find_startcode_internal(p, end);
70
6/6
✓ Branch 0 taken 2575 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1837 times.
✓ Branch 3 taken 738 times.
✓ Branch 4 taken 912 times.
✓ Branch 5 taken 925 times.
2581 if(p<out && out<end && !out[-1]) out--;
71 2581 return out;
72 }
73
74 738 static int nal_parse_units(AVIOContext *pb, NALUList *list,
75 const uint8_t *buf_in, int size)
76 {
77 738 const uint8_t *p = buf_in;
78 738 const uint8_t *end = p + size;
79 const uint8_t *nal_start, *nal_end;
80
81 738 size = 0;
82 738 nal_start = ff_nal_find_startcode(p, end);
83 1843 for (;;) {
84 2581 const size_t nalu_limit = SIZE_MAX / sizeof(*list->nalus);
85
4/4
✓ Branch 0 taken 6441 times.
✓ Branch 1 taken 738 times.
✓ Branch 2 taken 4598 times.
✓ Branch 3 taken 1843 times.
7179 while (nal_start < end && !*(nal_start++));
86
2/2
✓ Branch 0 taken 738 times.
✓ Branch 1 taken 1843 times.
2581 if (nal_start == end)
87 738 break;
88
89 1843 nal_end = ff_nal_find_startcode(nal_start, end);
90
2/2
✓ Branch 0 taken 1563 times.
✓ Branch 1 taken 280 times.
1843 if (pb) {
91 1563 avio_wb32(pb, nal_end - nal_start);
92 1563 avio_write(pb, nal_start, nal_end - nal_start);
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
280 } else if (list->nb_nalus >= nalu_limit) {
94 return AVERROR(ERANGE);
95 } else {
96 280 NALU *tmp = av_fast_realloc(list->nalus, &list->nalus_array_size,
97 280 (list->nb_nalus + 1) * sizeof(*list->nalus));
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
280 if (!tmp)
99 return AVERROR(ENOMEM);
100 280 list->nalus = tmp;
101 280 tmp[list->nb_nalus++] = (NALU){ .offset = nal_start - p,
102 280 .size = nal_end - nal_start };
103 }
104 1843 size += 4 + nal_end - nal_start;
105 1843 nal_start = nal_end;
106 }
107 738 return size;
108 }
109
110 659 int ff_nal_parse_units(AVIOContext *pb, const uint8_t *buf_in, int size)
111 {
112 659 return nal_parse_units(pb, NULL, buf_in, size);
113 }
114
115 79 int ff_nal_units_create_list(NALUList *list, const uint8_t *buf, int size)
116 {
117 79 list->nb_nalus = 0;
118 79 return nal_parse_units(NULL, list, buf, size);
119 }
120
121 79 void ff_nal_units_write_list(const NALUList *list, AVIOContext *pb,
122 const uint8_t *buf)
123 {
124
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 79 times.
359 for (unsigned i = 0; i < list->nb_nalus; i++) {
125 280 avio_wb32(pb, list->nalus[i].size);
126 280 avio_write(pb, buf + list->nalus[i].offset, list->nalus[i].size);
127 }
128 79 }
129
130 7 int ff_nal_parse_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
131 {
132 AVIOContext *pb;
133 7 int ret = avio_open_dyn_buf(&pb);
134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(ret < 0)
135 return ret;
136
137 7 ff_nal_parse_units(pb, buf_in, *size);
138
139 7 *size = avio_close_dyn_buf(pb, buf);
140 7 return 0;
141 }
142
143 const uint8_t *ff_nal_mp4_find_startcode(const uint8_t *start,
144 const uint8_t *end,
145 int nal_length_size)
146 {
147 unsigned int res = 0;
148
149 if (end - start < nal_length_size)
150 return NULL;
151 while (nal_length_size--)
152 res = (res << 8) | *start++;
153
154 if (res > end - start)
155 return NULL;
156
157 return start + res;
158 }
159
160 44 uint8_t *ff_nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len,
161 uint32_t *dst_len, int header_len)
162 {
163 uint8_t *dst;
164 uint32_t i, len;
165
166 44 dst = av_malloc(src_len + AV_INPUT_BUFFER_PADDING_SIZE);
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (!dst)
168 return NULL;
169
170 /* NAL unit header */
171 44 i = len = 0;
172
3/4
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
126 while (i < header_len && i < src_len)
173 82 dst[len++] = src[i++];
174
175
2/2
✓ Branch 0 taken 1637 times.
✓ Branch 1 taken 44 times.
1681 while (i + 2 < src_len)
176
6/6
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 1479 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 74 times.
✓ Branch 4 taken 74 times.
✓ Branch 5 taken 10 times.
1637 if (!src[i] && !src[i + 1] && src[i + 2] == 3) {
177 74 dst[len++] = src[i++];
178 74 dst[len++] = src[i++];
179 74 i++; // remove emulation_prevention_three_byte
180 } else
181 1563 dst[len++] = src[i++];
182
183
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 44 times.
132 while (i < src_len)
184 88 dst[len++] = src[i++];
185
186 44 memset(dst + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
187
188 44 *dst_len = len;
189 44 return dst;
190 }
191