FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg_mux.c
Date: 2026-10-20 22:17:59
Exec Total Coverage
Lines: 386 508 76.0%
Functions: 22 24 91.7%
Branches: 213 294 72.4%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <stdatomic.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "ffmpeg.h"
24 #include "ffmpeg_mux.h"
25 #include "ffmpeg_utils.h"
26 #include "sync_queue.h"
27
28 #include "libavutil/avstring.h"
29 #include "libavutil/fifo.h"
30 #include "libavutil/intreadwrite.h"
31 #include "libavutil/log.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/stereo3d.h"
34 #include "libavutil/time.h"
35 #include "libavutil/timestamp.h"
36
37 #include "libavcodec/packet.h"
38
39 #include "libavformat/avformat.h"
40 #include "libavformat/avio.h"
41
42 typedef struct MuxThreadContext {
43 AVPacket *pkt;
44 AVPacket *fix_sub_duration_pkt;
45 } MuxThreadContext;
46
47 65986 static Muxer *mux_from_of(OutputFile *of)
48 {
49 65986 return (Muxer*)of;
50 }
51
52 624948 static int64_t filesize(AVIOContext *pb)
53 {
54 624948 int64_t ret = -1;
55
56
2/2
✓ Branch 0 taken 609886 times.
✓ Branch 1 taken 15062 times.
624948 if (pb) {
57 609886 ret = avio_size(pb);
58
2/2
✓ Branch 0 taken 148798 times.
✓ Branch 1 taken 461088 times.
609886 if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too
59 148798 ret = avio_tell(pb);
60 }
61
62 624948 return ret;
63 }
64
65 ✗ static void mux_log_debug_ts(OutputStream *ost, const AVPacket *pkt)
66 {
67 static const char *desc[] = {
68 [LATENCY_PROBE_DEMUX] = "demux",
69 [LATENCY_PROBE_DEC_PRE] = "decode",
70 [LATENCY_PROBE_DEC_POST] = "decode",
71 [LATENCY_PROBE_FILTER_PRE] = "filter",
72 [LATENCY_PROBE_FILTER_POST] = "filter",
73 [LATENCY_PROBE_ENC_PRE] = "encode",
74 [LATENCY_PROBE_ENC_POST] = "encode",
75 [LATENCY_PROBE_NB] = "mux",
76 };
77
78 char latency[512];
79
80 ✗ *latency = 0;
81 ✗ if (pkt->opaque_ref) {
82 ✗ const FrameData *fd = (FrameData*)pkt->opaque_ref->data;
83 ✗ int64_t now = av_gettime_relative();
84 ✗ int64_t total = INT64_MIN;
85
86 int next;
87
88 ✗ for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i = next) {
89 ✗ int64_t val = fd->wallclock[i];
90
91 ✗ next = i + 1;
92
93 ✗ if (val == INT64_MIN)
94 ✗ continue;
95
96 ✗ if (total == INT64_MIN) {
97 ✗ total = now - val;
98 ✗ snprintf(latency, sizeof(latency), "total:%gms", total / 1e3);
99 }
100
101 // find the next valid entry
102 ✗ for (; next <= FF_ARRAY_ELEMS(fd->wallclock); next++) {
103 ✗ int64_t val_next = (next == FF_ARRAY_ELEMS(fd->wallclock)) ?
104 ✗ now : fd->wallclock[next];
105 int64_t diff;
106
107 ✗ if (val_next == INT64_MIN)
108 ✗ continue;
109 ✗ diff = val_next - val;
110
111 // print those stages that take at least 5% of total
112 ✗ if (100. * diff > 5. * total) {
113 ✗ av_strlcat(latency, ", ", sizeof(latency));
114
115 ✗ if (!strcmp(desc[i], desc[next]))
116 ✗ av_strlcat(latency, desc[i], sizeof(latency));
117 else
118 ✗ av_strlcatf(latency, sizeof(latency), "%s-%s:",
119 desc[i], desc[next]);
120
121 ✗ av_strlcatf(latency, sizeof(latency), " %gms/%d%%",
122 ✗ diff / 1e3, (int)(100. * diff / total));
123 }
124
125 ✗ break;
126 }
127
128 }
129 }
130
131 ✗ av_log(ost, AV_LOG_INFO, "muxer <- pts:%s pts_time:%s dts:%s dts_time:%s "
132 "duration:%s duration_time:%s size:%d latency(%s)\n",
133 ✗ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base),
134 ✗ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base),
135 ✗ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
136 ✗ pkt->size, *latency ? latency : "N/A");
137 ✗ }
138
139 616009 static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
140 {
141 616009 OutputStream *ost = &ms->ost;
142
143 // rescale timestamps to the stream timebase
144
4/4
✓ Branch 0 taken 449812 times.
✓ Branch 1 taken 166197 times.
✓ Branch 2 taken 59191 times.
✓ Branch 3 taken 390621 times.
616009 if (ost->type == AVMEDIA_TYPE_AUDIO && !ost->enc) {
145 // use av_rescale_delta() for streamcopying audio, to preserve
146 // accuracy with coarse input timebases
147 59191 int duration = av_get_audio_frame_duration2(ost->st->codecpar, pkt->size);
148
149
2/2
✓ Branch 0 taken 17018 times.
✓ Branch 1 taken 42173 times.
59191 if (!duration)
150 17018 duration = ost->st->codecpar->frame_size;
151
152 118382 pkt->dts = av_rescale_delta(pkt->time_base, pkt->dts,
153 59191 (AVRational){1, ost->st->codecpar->sample_rate}, duration,
154 59191 &ms->ts_rescale_delta_last, ost->st->time_base);
155 59191 pkt->pts = pkt->dts;
156
157 59191 pkt->duration = av_rescale_q(pkt->duration, pkt->time_base, ost->st->time_base);
158 } else
159 556818 av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base);
160 616009 pkt->time_base = ost->st->time_base;
161
162
2/2
✓ Branch 0 taken 282493 times.
✓ Branch 1 taken 333516 times.
616009 if (!(mux->fc->oformat->flags & AVFMT_NOTIMESTAMPS)) {
163
2/2
✓ Branch 0 taken 282489 times.
✓ Branch 1 taken 4 times.
282493 if (pkt->dts != AV_NOPTS_VALUE &&
164
2/2
✓ Branch 0 taken 281372 times.
✓ Branch 1 taken 1117 times.
282489 pkt->pts != AV_NOPTS_VALUE &&
165
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 281370 times.
281372 pkt->dts > pkt->pts) {
166 2 av_log(ost, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64", replacing by guess\n",
167 pkt->dts, pkt->pts);
168 2 pkt->pts =
169 2 pkt->dts = av_clip64(ms->last_mux_dts, pkt->pts - 1, pkt->dts - 1) + 1;
170 }
171
6/6
✓ Branch 0 taken 100542 times.
✓ Branch 1 taken 181951 times.
✓ Branch 2 taken 1836 times.
✓ Branch 3 taken 98706 times.
✓ Branch 4 taken 1759 times.
✓ Branch 5 taken 77 times.
282493 if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) &&
172
2/2
✓ Branch 0 taken 282412 times.
✓ Branch 1 taken 4 times.
282416 pkt->dts != AV_NOPTS_VALUE &&
173
2/2
✓ Branch 0 taken 275712 times.
✓ Branch 1 taken 6700 times.
282412 ms->last_mux_dts != AV_NOPTS_VALUE) {
174 275712 int64_t max = ms->last_mux_dts + !(mux->fc->oformat->flags & AVFMT_TS_NONSTRICT);
175
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 275656 times.
275712 if (pkt->dts < max) {
176
4/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 33 times.
56 int loglevel = max - pkt->dts > 2 || ost->type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (exit_on_error)
178 ✗ loglevel = AV_LOG_ERROR;
179 56 av_log(ost, loglevel, "Non-monotonic DTS; "
180 "previous: %"PRId64", current: %"PRId64"; ",
181 ms->last_mux_dts, pkt->dts);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (exit_on_error) {
183 ✗ return AVERROR(EINVAL);
184 }
185
186 56 av_log(ost, loglevel, "changing to %"PRId64". This may result "
187 "in incorrect timestamps in the output file.\n",
188 max);
189
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (pkt->pts >= pkt->dts)
190 56 pkt->pts = FFMAX(pkt->pts, max);
191 56 pkt->dts = max;
192 }
193 }
194 }
195 616009 ms->last_mux_dts = pkt->dts;
196
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 616009 times.
616009 if (debug_ts)
198 ✗ mux_log_debug_ts(ost, pkt);
199
200 616009 return 0;
201 }
202
203 616009 static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
204 {
205 616009 MuxStream *ms = ms_from_ost(ost);
206 616009 AVFormatContext *s = mux->fc;
207 int64_t fs;
208 uint64_t frame_num;
209 int ret;
210
211 616009 fs = filesize(s->pb);
212 616009 atomic_store(&mux->last_filesize, fs);
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 616009 times.
616009 if (fs >= mux->limit_filesize) {
214 ✗ ret = AVERROR_EOF;
215 ✗ goto fail;
216 }
217
218 616009 ret = mux_fixup_ts(mux, ms, pkt);
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 616009 times.
616009 if (ret < 0)
220 ✗ goto fail;
221
222 616009 ms->data_size_mux += pkt->size;
223 616009 frame_num = atomic_fetch_add(&ost->packets_written, 1);
224
225 616009 pkt->stream_index = ost->index;
226
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 616009 times.
616009 if (ms->stats.io)
228 ✗ enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num);
229
230 616009 ret = av_interleaved_write_frame(s, pkt);
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 616009 times.
616009 if (ret < 0) {
232 ✗ av_log(ost, AV_LOG_ERROR,
233 "Error submitting a packet to the muxer: %s\n",
234 ✗ av_err2str(ret));
235 ✗ goto fail;
236 }
237
238 616009 return 0;
239 ✗ fail:
240 ✗ av_packet_unref(pkt);
241 ✗ return ret;
242 }
243
244 625634 static int sync_queue_process(Muxer *mux, MuxStream *ms, AVPacket *pkt, int *stream_eof)
245 {
246 625634 OutputFile *of = &mux->of;
247
248
2/2
✓ Branch 0 taken 1019 times.
✓ Branch 1 taken 624615 times.
625634 if (ms->sq_idx_mux >= 0) {
249 1019 int ret = sq_send(mux->sq_mux, ms->sq_idx_mux, SQPKT(pkt));
250
2/2
✓ Branch 0 taken 957 times.
✓ Branch 1 taken 62 times.
1019 if (ret < 0) {
251
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (ret == AVERROR_EOF)
252 62 *stream_eof = 1;
253
254 62 return ret;
255 }
256
257 895 while (1) {
258 1852 ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt));
259
2/2
✓ Branch 0 taken 957 times.
✓ Branch 1 taken 895 times.
1852 if (ret < 0) {
260 /* n.b.: We forward EOF from the sync queue, terminating muxing.
261 * This assumes that if a muxing sync queue is present, then all
262 * the streams use it. That is true currently, but may change in
263 * the future, then this code needs to be revisited.
264 */
265
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 935 times.
957 return ret == AVERROR(EAGAIN) ? 0 : ret;
266 }
267
268 895 ret = write_packet(mux, of->streams[ret],
269 mux->sq_pkt);
270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 895 times.
895 if (ret < 0)
271 ✗ return ret;
272 }
273
2/2
✓ Branch 0 taken 615114 times.
✓ Branch 1 taken 9501 times.
624615 } else if (pkt)
274 615114 return write_packet(mux, &ms->ost, pkt);
275
276 9501 return 0;
277 }
278
279 static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt);
280
281 /* apply the output bitstream filters */
282 626761 static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt,
283 OutputStream *ost, AVPacket *pkt, int *stream_eof)
284 {
285 626761 MuxStream *ms = ms_from_ost(ost);
286 const char *err_msg;
287 int ret;
288
289
4/4
✓ Branch 0 taken 617342 times.
✓ Branch 1 taken 9419 times.
✓ Branch 2 taken 80792 times.
✓ Branch 3 taken 536550 times.
626761 if (pkt && !ost->enc) {
290 80792 ret = of_streamcopy(&mux->of, ost, pkt);
291
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 80519 times.
80792 if (ret == AVERROR(EAGAIN))
292 273 return 0;
293
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 80451 times.
80519 else if (ret == AVERROR_EOF) {
294 68 av_packet_unref(pkt);
295 68 pkt = NULL;
296 68 *stream_eof = 1;
297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80451 times.
80451 } else if (ret < 0)
298 ✗ goto fail;
299 }
300
301 // emit heartbeat for -fix_sub_duration;
302 // we are only interested in heartbeats on on random access points.
303
4/4
✓ Branch 0 taken 617001 times.
✓ Branch 1 taken 9487 times.
✓ Branch 2 taken 576371 times.
✓ Branch 3 taken 40630 times.
626488 if (pkt && (pkt->flags & AV_PKT_FLAG_KEY)) {
304 576371 mt->fix_sub_duration_pkt->opaque = (void*)(intptr_t)PKT_OPAQUE_FIX_SUB_DURATION;
305 576371 mt->fix_sub_duration_pkt->pts = pkt->pts;
306 576371 mt->fix_sub_duration_pkt->time_base = pkt->time_base;
307
308 576371 ret = sch_mux_sub_heartbeat(mux->sch, mux->sch_idx, ms->sch_idx,
309 576371 mt->fix_sub_duration_pkt);
310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 576371 times.
576371 if (ret < 0)
311 ✗ goto fail;
312 }
313
314
2/2
✓ Branch 0 taken 11336 times.
✓ Branch 1 taken 615152 times.
626488 if (ms->bsf_ctx) {
315 11336 int bsf_eof = 0;
316
317
2/2
✓ Branch 0 taken 11177 times.
✓ Branch 1 taken 159 times.
11336 if (pkt)
318 11177 av_packet_rescale_ts(pkt, pkt->time_base, ms->bsf_ctx->time_base_in);
319
320 11336 ret = av_bsf_send_packet(ms->bsf_ctx, pkt);
321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11336 times.
11336 if (ret < 0) {
322 ✗ err_msg = "submitting a packet for bitstream filtering";
323 ✗ goto fail;
324 }
325
326
2/2
✓ Branch 0 taken 21697 times.
✓ Branch 1 taken 186 times.
21883 while (!bsf_eof) {
327 21697 ret = av_bsf_receive_packet(ms->bsf_ctx, ms->bsf_pkt);
328
2/2
✓ Branch 0 taken 11139 times.
✓ Branch 1 taken 10558 times.
21697 if (ret == AVERROR(EAGAIN))
329 11139 return 0;
330
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 10371 times.
10558 else if (ret == AVERROR_EOF)
331 187 bsf_eof = 1;
332
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 10295 times.
10371 else if (ret < 0) {
333 76 av_log(ost, AV_LOG_ERROR,
334 "Error applying bitstream filters to a packet: %s",
335 76 av_err2str(ret));
336
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 74 times.
76 if (exit_on_error)
337 2 return ret;
338 74 continue;
339 }
340
341
2/2
✓ Branch 0 taken 10295 times.
✓ Branch 1 taken 187 times.
10482 if (!bsf_eof)
342 10295 ms->bsf_pkt->time_base = ms->bsf_ctx->time_base_out;
343
344
2/2
✓ Branch 0 taken 10295 times.
✓ Branch 1 taken 187 times.
10482 ret = sync_queue_process(mux, ms, bsf_eof ? NULL : ms->bsf_pkt, stream_eof);
345
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10473 times.
10482 if (ret < 0)
346 9 goto mux_fail;
347 }
348 186 *stream_eof = 1;
349 } else {
350 615152 ret = sync_queue_process(mux, ms, pkt, stream_eof);
351
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 615077 times.
615152 if (ret < 0)
352 75 goto mux_fail;
353 }
354
355
2/2
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 615010 times.
615263 return *stream_eof ? AVERROR_EOF : 0;
356
357 84 mux_fail:
358 84 err_msg = "submitting a packet to the muxer";
359
360 84 fail:
361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (ret != AVERROR_EOF)
362 ✗ av_log(ost, AV_LOG_ERROR, "Error %s: %s\n", err_msg, av_err2str(ret));
363 84 return ret;
364 }
365
366 8939 static void thread_set_name(Muxer *mux)
367 {
368 char name[16];
369 8939 snprintf(name, sizeof(name), "mux%d:%s",
370 8939 mux->of.index, mux->fc->oformat->name);
371 8939 ff_thread_setname(name);
372 8939 }
373
374 8939 static void mux_thread_uninit(MuxThreadContext *mt)
375 {
376 8939 av_packet_free(&mt->pkt);
377 8939 av_packet_free(&mt->fix_sub_duration_pkt);
378
379 8939 memset(mt, 0, sizeof(*mt));
380 8939 }
381
382 8939 static int mux_thread_init(MuxThreadContext *mt)
383 {
384 8939 memset(mt, 0, sizeof(*mt));
385
386 8939 mt->pkt = av_packet_alloc();
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8939 times.
8939 if (!mt->pkt)
388 ✗ goto fail;
389
390 8939 mt->fix_sub_duration_pkt = av_packet_alloc();
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8939 times.
8939 if (!mt->fix_sub_duration_pkt)
392 ✗ goto fail;
393
394 8939 return 0;
395
396 ✗ fail:
397 ✗ mux_thread_uninit(mt);
398 ✗ return AVERROR(ENOMEM);
399 }
400
401 8939 int muxer_thread(void *arg)
402 {
403 8939 Muxer *mux = arg;
404 8939 OutputFile *of = &mux->of;
405
406 MuxThreadContext mt;
407
408 8939 int ret = 0;
409
410 8939 ret = mux_thread_init(&mt);
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8939 times.
8939 if (ret < 0)
412 ✗ goto finish;
413
414 8939 thread_set_name(mux);
415
416 626737 while (1) {
417 OutputStream *ost;
418 635676 int stream_idx, stream_eof = 0;
419
420 635676 ret = sch_mux_receive(mux->sch, of->index, mt.pkt);
421 635676 stream_idx = mt.pkt->stream_index;
422
2/2
✓ Branch 0 taken 8915 times.
✓ Branch 1 taken 626761 times.
635676 if (stream_idx < 0) {
423 8915 av_log(mux, AV_LOG_VERBOSE, "All streams finished\n");
424 8915 ret = 0;
425 8939 break;
426 }
427
428 626761 ost = of->streams[mux->sch_stream_idx[stream_idx]];
429 626761 mt.pkt->stream_index = ost->index;
430 626761 mt.pkt->flags &= ~AV_PKT_FLAG_TRUSTED;
431
432
2/2
✓ Branch 0 taken 617342 times.
✓ Branch 1 taken 9419 times.
626761 ret = mux_packet_filter(mux, &mt, ost, ret < 0 ? NULL : mt.pkt, &stream_eof);
433 626761 av_packet_unref(mt.pkt);
434
2/2
✓ Branch 0 taken 337 times.
✓ Branch 1 taken 626424 times.
626761 if (ret == AVERROR_EOF) {
435
2/2
✓ Branch 0 taken 315 times.
✓ Branch 1 taken 22 times.
337 if (stream_eof) {
436 315 sch_mux_receive_finish(mux->sch, of->index, stream_idx);
437 } else {
438 22 av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n");
439 22 ret = 0;
440 22 break;
441 }
442
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 626422 times.
626424 } else if (ret < 0) {
443 2 av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n");
444 2 break;
445 }
446 }
447
448 8939 finish:
449 8939 mux_thread_uninit(&mt);
450
451 8939 return ret;
452 }
453
454 80792 static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt)
455 {
456 80792 MuxStream *ms = ms_from_ost(ost);
457
1/2
✓ Branch 0 taken 80792 times.
✗ Branch 1 not taken.
80792 FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL;
458
1/2
✓ Branch 0 taken 80792 times.
✗ Branch 1 not taken.
80792 int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE;
459
2/2
✓ Branch 0 taken 1073 times.
✓ Branch 1 taken 79719 times.
80792 int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
460 int64_t ts_offset;
461
462
2/2
✓ Branch 0 taken 1666 times.
✓ Branch 1 taken 79126 times.
80792 if (of->recording_time != INT64_MAX &&
463
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 1598 times.
1666 dts >= of->recording_time + start_time)
464 68 return AVERROR_EOF;
465
466
4/4
✓ Branch 0 taken 1229 times.
✓ Branch 1 taken 79495 times.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 1139 times.
80724 if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) &&
467
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 !ms->copy_initial_nonkeyframes)
468 90 return AVERROR(EAGAIN);
469
470
2/2
✓ Branch 0 taken 1139 times.
✓ Branch 1 taken 79495 times.
80634 if (!ms->streamcopy_started) {
471
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1139 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1139 if (!ms->copy_prior_start &&
472 ✗ (pkt->pts == AV_NOPTS_VALUE ?
473 ✗ dts < ms->ts_copy_start :
474 ✗ pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base)))
475 ✗ return AVERROR(EAGAIN);
476
477
4/4
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 952 times.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 4 times.
1139 if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time)
478 183 return AVERROR(EAGAIN);
479 }
480
481 80451 ts_offset = av_rescale_q(start_time, AV_TIME_BASE_Q, pkt->time_base);
482
483
2/2
✓ Branch 0 taken 71859 times.
✓ Branch 1 taken 8592 times.
80451 if (pkt->pts != AV_NOPTS_VALUE)
484 71859 pkt->pts -= ts_offset;
485
486
2/2
✓ Branch 0 taken 8376 times.
✓ Branch 1 taken 72075 times.
80451 if (pkt->dts == AV_NOPTS_VALUE) {
487 8376 pkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, pkt->time_base);
488
2/2
✓ Branch 0 taken 59319 times.
✓ Branch 1 taken 12756 times.
72075 } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
489 59319 pkt->pts = pkt->dts - ts_offset;
490 }
491
492 80451 pkt->dts -= ts_offset;
493
494 80451 ms->streamcopy_started = 1;
495
496 80451 return 0;
497 }
498
499 int print_sdp(const char *filename);
500
501 ✗ int print_sdp(const char *filename)
502 {
503 char sdp[16384];
504 ✗ int j = 0, ret;
505 AVIOContext *sdp_pb;
506 AVFormatContext **avc;
507
508 ✗ avc = av_malloc_array(nb_output_files, sizeof(*avc));
509 ✗ if (!avc)
510 ✗ return AVERROR(ENOMEM);
511 ✗ for (int i = 0; i < nb_output_files; i++) {
512 ✗ Muxer *mux = mux_from_of(output_files[i]);
513
514 ✗ if (!strcmp(mux->fc->oformat->name, "rtp")) {
515 ✗ avc[j] = mux->fc;
516 ✗ j++;
517 }
518 }
519
520 ✗ if (!j) {
521 ✗ av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n");
522 ✗ ret = AVERROR(EINVAL);
523 ✗ goto fail;
524 }
525
526 ✗ ret = av_sdp_create(avc, j, sdp, sizeof(sdp));
527 ✗ if (ret < 0)
528 ✗ goto fail;
529
530 ✗ if (!filename) {
531 ✗ printf("SDP:\n%s\n", sdp);
532 ✗ fflush(stdout);
533 } else {
534 ✗ ret = avio_open2(&sdp_pb, filename, AVIO_FLAG_WRITE, &int_cb, NULL);
535 ✗ if (ret < 0) {
536 ✗ av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", filename);
537 ✗ goto fail;
538 }
539
540 ✗ avio_print(sdp_pb, sdp);
541 ✗ avio_closep(&sdp_pb);
542 }
543
544 ✗ fail:
545 ✗ av_freep(&avc);
546 ✗ return ret;
547 }
548
549 8939 int mux_check_init(void *arg)
550 {
551 8939 Muxer *mux = arg;
552 8939 OutputFile *of = &mux->of;
553 8939 AVFormatContext *fc = mux->fc;
554 int ret;
555
556 8939 ret = avformat_write_header(fc, &mux->opts);
557
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8939 times.
8939 if (ret < 0) {
558 ✗ av_log(mux, AV_LOG_ERROR, "Could not write header (incorrect codec "
559 ✗ "parameters ?): %s\n", av_err2str(ret));
560 ✗ return ret;
561 }
562 //assert_avoptions(of->opts);
563 8939 mux->header_written = 1;
564
565 8939 av_dump_format(fc, of->index, fc->url, 1);
566 8939 atomic_fetch_add(&nb_output_dumped, 1);
567
568 8939 return 0;
569 }
570
571 9599 static int bsf_init(MuxStream *ms)
572 {
573 9599 OutputStream *ost = &ms->ost;
574 9599 AVBSFContext *ctx = ms->bsf_ctx;
575 int ret;
576
577
2/2
✓ Branch 0 taken 9402 times.
✓ Branch 1 taken 197 times.
9599 if (!ctx)
578 9402 return avcodec_parameters_copy(ost->st->codecpar, ms->par_in);
579
580 197 ret = avcodec_parameters_copy(ctx->par_in, ms->par_in);
581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (ret < 0)
582 ✗ return ret;
583
584 197 ctx->time_base_in = ost->st->time_base;
585
586 197 ret = av_bsf_init(ctx);
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (ret < 0) {
588 ✗ av_log(ms, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n",
589 ✗ ctx->filter->name);
590 ✗ return ret;
591 }
592
593 197 ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out);
594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (ret < 0)
595 ✗ return ret;
596 197 ost->st->time_base = ctx->time_base_out;
597
598 197 ms->bsf_pkt = av_packet_alloc();
599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (!ms->bsf_pkt)
600 ✗ return AVERROR(ENOMEM);
601
602 197 return 0;
603 }
604
605 9599 int of_stream_init(OutputFile *of, OutputStream *ost,
606 const AVCodecContext *enc_ctx)
607 {
608 9599 Muxer *mux = mux_from_of(of);
609 9599 MuxStream *ms = ms_from_ost(ost);
610 int ret;
611
612
2/2
✓ Branch 0 taken 8618 times.
✓ Branch 1 taken 981 times.
9599 if (enc_ctx) {
613 // use upstream time base unless it has been overridden previously
614
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8614 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8618 if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0)
615 8614 ost->st->time_base = av_add_q(enc_ctx->time_base, (AVRational){0, 1});
616
617 8618 ost->st->avg_frame_rate = enc_ctx->framerate;
618 8618 ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio;
619
620 8618 ret = avcodec_parameters_from_context(ms->par_in, enc_ctx);
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8618 times.
8618 if (ret < 0) {
622 ✗ av_log(ost, AV_LOG_FATAL,
623 "Error initializing the output stream codec parameters.\n");
624 ✗ return ret;
625 }
626 }
627
628 /* initialize bitstream filters for the output stream
629 * needs to be done here, because the codec id for streamcopy is not
630 * known until now */
631 9599 ret = bsf_init(ms);
632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9599 times.
9599 if (ret < 0)
633 ✗ return ret;
634
635
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9594 times.
9599 if (ms->stereo3d_set) {
636 5 AVCodecParameters *par = ost->st->codecpar;
637 AVStereo3D *stereo;
638 size_t size;
639
640 5 stereo = av_stereo3d_alloc_size(&size);
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!stereo)
642 ✗ return AVERROR(ENOMEM);
643 5 stereo->type = ms->stereo3d_type;
644
645
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
5 if (av_packet_side_data_get(par->coded_side_data, par->nb_coded_side_data,
646 AV_PKT_DATA_STEREO3D))
647 2 av_log(ost, AV_LOG_INFO, "Overriding existing stereoscopic 3D side data\n");
648
649
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (!av_packet_side_data_add(&par->coded_side_data, &par->nb_coded_side_data,
650 AV_PKT_DATA_STEREO3D, stereo, size, 0)) {
651 ✗ av_freep(&stereo);
652 ✗ return AVERROR(ENOMEM);
653 }
654
655 /* Keep Matroska/WebM metadata consistent with the explicit layout,
656 * as their muxer consults the tag before the side data. */
657
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (!strcmp(mux->fc->oformat->name, "matroska") ||
658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 !strcmp(mux->fc->oformat->name, "webm")) {
659 4 const char *stereo_mode =
660
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 ms->stereo3d_type == AV_STEREO3D_2D ? "mono" :
661
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 ms->stereo3d_type == AV_STEREO3D_SIDEBYSIDE ? "left_right" :
662 "top_bottom";
663 4 ret = av_dict_set(&ost->st->metadata, "stereo_mode", stereo_mode, 0);
664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
665 ✗ return ret;
666 }
667 }
668
669
2/2
✓ Branch 0 taken 6306 times.
✓ Branch 1 taken 3293 times.
9599 if (ms->stream_duration) {
670 6306 ost->st->duration = av_rescale_q(ms->stream_duration, ms->stream_duration_tb,
671 6306 ost->st->time_base);
672 }
673
674
2/2
✓ Branch 0 taken 9598 times.
✓ Branch 1 taken 1 times.
9599 if (ms->sch_idx >= 0)
675 9598 return sch_mux_stream_ready(mux->sch, of->index, ms->sch_idx);
676
677 1 return 0;
678 }
679
680 8939 static int check_written(OutputFile *of)
681 {
682 8939 int64_t total_packets_written = 0;
683 8939 int pass1_used = 1;
684 8939 int ret = 0;
685
686
2/2
✓ Branch 0 taken 9599 times.
✓ Branch 1 taken 8939 times.
18538 for (int i = 0; i < of->nb_streams; i++) {
687 9599 OutputStream *ost = of->streams[i];
688 9599 uint64_t packets_written = atomic_load(&ost->packets_written);
689
690 9599 total_packets_written += packets_written;
691
692
2/2
✓ Branch 0 taken 8618 times.
✓ Branch 1 taken 981 times.
9599 if (ost->enc &&
693
2/2
✓ Branch 0 taken 8610 times.
✓ Branch 1 taken 8 times.
8618 (ost->enc->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2))
694 != AV_CODEC_FLAG_PASS1)
695 8610 pass1_used = 0;
696
697
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 9499 times.
9599 if (!packets_written &&
698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) {
699 ✗ av_log(ost, AV_LOG_FATAL, "Empty output stream\n");
700 ✗ ret = err_merge(ret, AVERROR(EINVAL));
701 }
702 }
703
704
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 8908 times.
8939 if (!total_packets_written) {
705 31 int level = AV_LOG_WARNING;
706
707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT) {
708 ✗ ret = err_merge(ret, AVERROR(EINVAL));
709 ✗ level = AV_LOG_FATAL;
710 }
711
712
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 5 times.
31 av_log(of, level, "Output file is empty, nothing was encoded%s\n",
713 pass1_used ? "" : "(check -ss / -t / -frames parameters if used)");
714 }
715
716 8939 return ret;
717 }
718
719 8939 static void mux_final_stats(Muxer *mux)
720 {
721 8939 OutputFile *of = &mux->of;
722 8939 uint64_t total_packets = 0, total_size = 0;
723 8939 uint64_t video_size = 0, audio_size = 0, subtitle_size = 0,
724 8939 extra_size = 0, other_size = 0;
725
726 8939 uint8_t overhead[16] = "unknown";
727 8939 int64_t file_size = of_filesize(of);
728
729 8939 av_log(of, AV_LOG_VERBOSE, "Output file #%d (%s):\n",
730 of->index, of->url);
731
732
2/2
✓ Branch 0 taken 9599 times.
✓ Branch 1 taken 8939 times.
18538 for (int j = 0; j < of->nb_streams; j++) {
733 9599 OutputStream *ost = of->streams[j];
734 9599 MuxStream *ms = ms_from_ost(ost);
735 9599 const AVCodecParameters *par = ost->st->codecpar;
736 9599 const enum AVMediaType type = par->codec_type;
737 9599 const uint64_t s = ms->data_size_mux;
738
739
4/4
✓ Branch 0 taken 7463 times.
✓ Branch 1 taken 2039 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 13 times.
9599 switch (type) {
740 7463 case AVMEDIA_TYPE_VIDEO: video_size += s; break;
741 2039 case AVMEDIA_TYPE_AUDIO: audio_size += s; break;
742 84 case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break;
743 13 default: other_size += s; break;
744 }
745
746 9599 extra_size += par->extradata_size;
747 9599 total_size += s;
748 9599 total_packets += atomic_load(&ost->packets_written);
749
750 9599 av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ",
751 of->index, j, av_get_media_type_string(type));
752
2/2
✓ Branch 0 taken 8618 times.
✓ Branch 1 taken 981 times.
9599 if (ost->enc) {
753 8618 av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded",
754 8618 ost->enc->frames_encoded);
755
2/2
✓ Branch 0 taken 1584 times.
✓ Branch 1 taken 7034 times.
8618 if (type == AVMEDIA_TYPE_AUDIO)
756 1584 av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->enc->samples_encoded);
757 8618 av_log(of, AV_LOG_VERBOSE, "; ");
758 }
759
760 9599 av_log(of, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ",
761 9599 atomic_load(&ost->packets_written), s);
762
763 9599 av_log(of, AV_LOG_VERBOSE, "\n");
764 }
765
766 8939 av_log(of, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n",
767 total_packets, total_size);
768
769
6/6
✓ Branch 0 taken 8907 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 8753 times.
✓ Branch 3 taken 154 times.
✓ Branch 4 taken 6466 times.
✓ Branch 5 taken 2287 times.
8939 if (total_size && file_size > 0 && file_size >= total_size) {
770 6466 snprintf(overhead, sizeof(overhead), "%f%%",
771 6466 100.0 * (file_size - total_size) / total_size);
772 }
773
774 8939 av_log(of, AV_LOG_INFO,
775 "video:%1.0fKiB audio:%1.0fKiB subtitle:%1.0fKiB other streams:%1.0fKiB "
776 "global headers:%1.0fKiB muxing overhead: %s\n",
777 video_size / 1024.0,
778 audio_size / 1024.0,
779 subtitle_size / 1024.0,
780 other_size / 1024.0,
781 extra_size / 1024.0,
782 overhead);
783 8939 }
784
785 8940 int of_write_trailer(OutputFile *of)
786 {
787 8940 Muxer *mux = mux_from_of(of);
788 8940 AVFormatContext *fc = mux->fc;
789 8940 int ret, mux_result = 0;
790
791
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8939 times.
8940 if (!mux->header_written) {
792 1 av_log(mux, AV_LOG_ERROR,
793 "Nothing was written into output file, because "
794 "at least one of its streams received no packets.\n");
795 1 return AVERROR(EINVAL);
796 }
797
798 8939 ret = av_write_trailer(fc);
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8939 times.
8939 if (ret < 0) {
800 ✗ av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret));
801 ✗ mux_result = err_merge(mux_result, ret);
802 }
803
804 8939 mux->last_filesize = filesize(fc->pb);
805
806
2/2
✓ Branch 0 taken 8783 times.
✓ Branch 1 taken 156 times.
8939 if (!(fc->oformat->flags & AVFMT_NOFILE)) {
807 8783 ret = avio_closep(&fc->pb);
808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8783 times.
8783 if (ret < 0) {
809 ✗ av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret));
810 ✗ mux_result = err_merge(mux_result, ret);
811 }
812 }
813
814 8939 mux_final_stats(mux);
815
816 // check whether anything was actually written
817 8939 ret = check_written(of);
818 8939 mux_result = err_merge(mux_result, ret);
819
820 8939 return mux_result;
821 }
822
823 28812 static void enc_stats_uninit(EncStats *es)
824 {
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28812 times.
28812 for (int i = 0; i < es->nb_components; i++)
826 ✗ av_freep(&es->components[i].str);
827 28812 av_freep(&es->components);
828
829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28812 times.
28812 if (es->lock_initialized)
830 ✗ pthread_mutex_destroy(&es->lock);
831 28812 es->lock_initialized = 0;
832 28812 }
833
834 9604 static void ost_free(OutputStream **post)
835 {
836 9604 OutputStream *ost = *post;
837 MuxStream *ms;
838
839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9604 times.
9604 if (!ost)
840 ✗ return;
841 9604 ms = ms_from_ost(ost);
842
843 9604 enc_free(&ost->enc);
844 9604 fg_free(&ost->fg_simple);
845
846
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9596 times.
9604 if (ost->logfile) {
847
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (fclose(ost->logfile))
848 ✗ av_log(ms, AV_LOG_ERROR,
849 "Error closing logfile, loss of information possible: %s\n",
850 ✗ av_err2str(AVERROR(errno)));
851 8 ost->logfile = NULL;
852 }
853
854 9604 avcodec_parameters_free(&ms->par_in);
855
856 9604 av_bsf_free(&ms->bsf_ctx);
857 9604 av_packet_free(&ms->bsf_pkt);
858
859 9604 av_packet_free(&ms->pkt);
860
861 9604 av_freep(&ost->kf.pts);
862 9604 av_expr_free(ost->kf.pexpr);
863
864 9604 av_freep(&ost->logfile_prefix);
865
866 9604 av_freep(&ost->attachment_filename);
867
868 9604 enc_stats_uninit(&ost->enc_stats_pre);
869 9604 enc_stats_uninit(&ost->enc_stats_post);
870 9604 enc_stats_uninit(&ms->stats);
871
872 9604 av_freep(post);
873 }
874
875 8945 static void fc_close(AVFormatContext **pfc)
876 {
877 8945 AVFormatContext *fc = *pfc;
878
879
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8944 times.
8945 if (!fc)
880 1 return;
881
882
2/2
✓ Branch 0 taken 8784 times.
✓ Branch 1 taken 160 times.
8944 if (!(fc->oformat->flags & AVFMT_NOFILE))
883 8784 avio_closep(&fc->pb);
884 8944 avformat_free_context(fc);
885
886 8944 *pfc = NULL;
887 }
888
889 8945 void of_free(OutputFile **pof)
890 {
891 8945 OutputFile *of = *pof;
892 Muxer *mux;
893
894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8945 times.
8945 if (!of)
895 ✗ return;
896 8945 mux = mux_from_of(of);
897
898 8945 sq_free(&mux->sq_mux);
899
900
2/2
✓ Branch 0 taken 9604 times.
✓ Branch 1 taken 8945 times.
18549 for (int i = 0; i < of->nb_streams; i++)
901 9604 ost_free(&of->streams[i]);
902 8945 av_freep(&of->streams);
903
904 8945 av_freep(&mux->sch_stream_idx);
905
906 8945 av_dict_free(&mux->opts);
907 8945 av_dict_free(&mux->enc_opts_used);
908
909 8945 av_packet_free(&mux->sq_pkt);
910
911 8945 fc_close(&mux->fc);
912
913 8945 av_freep(pof);
914 }
915
916 38502 int64_t of_filesize(OutputFile *of)
917 {
918 38502 Muxer *mux = mux_from_of(of);
919 38502 return atomic_load(&mux->last_filesize);
920 }
921