FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg_mux.c
Date: 2026-08-15 14:54:27
Exec Total Coverage
Lines: 370 491 75.4%
Functions: 22 24 91.7%
Branches: 196 276 71.0%

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/time.h"
34 #include "libavutil/timestamp.h"
35
36 #include "libavcodec/packet.h"
37
38 #include "libavformat/avformat.h"
39 #include "libavformat/avio.h"
40
41 typedef struct MuxThreadContext {
42 AVPacket *pkt;
43 AVPacket *fix_sub_duration_pkt;
44 } MuxThreadContext;
45
46 63144 static Muxer *mux_from_of(OutputFile *of)
47 {
48 63144 return (Muxer*)of;
49 }
50
51 608204 static int64_t filesize(AVIOContext *pb)
52 {
53 608204 int64_t ret = -1;
54
55
2/2
✓ Branch 0 taken 596592 times.
✓ Branch 1 taken 11612 times.
608204 if (pb) {
56 596592 ret = avio_size(pb);
57
2/2
✓ Branch 0 taken 146962 times.
✓ Branch 1 taken 449630 times.
596592 if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too
58 146962 ret = avio_tell(pb);
59 }
60
61 608204 return ret;
62 }
63
64 static void mux_log_debug_ts(OutputStream *ost, const AVPacket *pkt)
65 {
66 static const char *desc[] = {
67 [LATENCY_PROBE_DEMUX] = "demux",
68 [LATENCY_PROBE_DEC_PRE] = "decode",
69 [LATENCY_PROBE_DEC_POST] = "decode",
70 [LATENCY_PROBE_FILTER_PRE] = "filter",
71 [LATENCY_PROBE_FILTER_POST] = "filter",
72 [LATENCY_PROBE_ENC_PRE] = "encode",
73 [LATENCY_PROBE_ENC_POST] = "encode",
74 [LATENCY_PROBE_NB] = "mux",
75 };
76
77 char latency[512];
78
79 *latency = 0;
80 if (pkt->opaque_ref) {
81 const FrameData *fd = (FrameData*)pkt->opaque_ref->data;
82 int64_t now = av_gettime_relative();
83 int64_t total = INT64_MIN;
84
85 int next;
86
87 for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i = next) {
88 int64_t val = fd->wallclock[i];
89
90 next = i + 1;
91
92 if (val == INT64_MIN)
93 continue;
94
95 if (total == INT64_MIN) {
96 total = now - val;
97 snprintf(latency, sizeof(latency), "total:%gms", total / 1e3);
98 }
99
100 // find the next valid entry
101 for (; next <= FF_ARRAY_ELEMS(fd->wallclock); next++) {
102 int64_t val_next = (next == FF_ARRAY_ELEMS(fd->wallclock)) ?
103 now : fd->wallclock[next];
104 int64_t diff;
105
106 if (val_next == INT64_MIN)
107 continue;
108 diff = val_next - val;
109
110 // print those stages that take at least 5% of total
111 if (100. * diff > 5. * total) {
112 av_strlcat(latency, ", ", sizeof(latency));
113
114 if (!strcmp(desc[i], desc[next]))
115 av_strlcat(latency, desc[i], sizeof(latency));
116 else
117 av_strlcatf(latency, sizeof(latency), "%s-%s:",
118 desc[i], desc[next]);
119
120 av_strlcatf(latency, sizeof(latency), " %gms/%d%%",
121 diff / 1e3, (int)(100. * diff / total));
122 }
123
124 break;
125 }
126
127 }
128 }
129
130 av_log(ost, AV_LOG_INFO, "muxer <- pts:%s pts_time:%s dts:%s dts_time:%s "
131 "duration:%s duration_time:%s size:%d latency(%s)\n",
132 av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base),
133 av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base),
134 av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
135 pkt->size, *latency ? latency : "N/A");
136 }
137
138 599507 static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
139 {
140 599507 OutputStream *ost = &ms->ost;
141
142 // rescale timestamps to the stream timebase
143
4/4
✓ Branch 0 taken 435116 times.
✓ Branch 1 taken 164391 times.
✓ Branch 2 taken 53734 times.
✓ Branch 3 taken 381382 times.
599507 if (ost->type == AVMEDIA_TYPE_AUDIO && !ost->enc) {
144 // use av_rescale_delta() for streamcopying audio, to preserve
145 // accuracy with coarse input timebases
146 53734 int duration = av_get_audio_frame_duration2(ost->st->codecpar, pkt->size);
147
148
2/2
✓ Branch 0 taken 16681 times.
✓ Branch 1 taken 37053 times.
53734 if (!duration)
149 16681 duration = ost->st->codecpar->frame_size;
150
151 107468 pkt->dts = av_rescale_delta(pkt->time_base, pkt->dts,
152 53734 (AVRational){1, ost->st->codecpar->sample_rate}, duration,
153 53734 &ms->ts_rescale_delta_last, ost->st->time_base);
154 53734 pkt->pts = pkt->dts;
155
156 53734 pkt->duration = av_rescale_q(pkt->duration, pkt->time_base, ost->st->time_base);
157 } else
158 545773 av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base);
159 599507 pkt->time_base = ost->st->time_base;
160
161
2/2
✓ Branch 0 taken 270200 times.
✓ Branch 1 taken 329307 times.
599507 if (!(mux->fc->oformat->flags & AVFMT_NOTIMESTAMPS)) {
162
1/2
✓ Branch 0 taken 270200 times.
✗ Branch 1 not taken.
270200 if (pkt->dts != AV_NOPTS_VALUE &&
163
2/2
✓ Branch 0 taken 269103 times.
✓ Branch 1 taken 1097 times.
270200 pkt->pts != AV_NOPTS_VALUE &&
164
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 269101 times.
269103 pkt->dts > pkt->pts) {
165 2 av_log(ost, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64", replacing by guess\n",
166 pkt->dts, pkt->pts);
167 2 pkt->pts =
168 2 pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1
169 2 - FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1)
170 2 - FFMAX3(pkt->pts, pkt->dts, ms->last_mux_dts + 1);
171 }
172
6/6
✓ Branch 0 taken 99062 times.
✓ Branch 1 taken 171138 times.
✓ Branch 2 taken 1826 times.
✓ Branch 3 taken 97236 times.
✓ Branch 4 taken 1749 times.
✓ Branch 5 taken 77 times.
270200 if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) &&
173
1/2
✓ Branch 0 taken 270123 times.
✗ Branch 1 not taken.
270123 pkt->dts != AV_NOPTS_VALUE &&
174
2/2
✓ Branch 0 taken 263704 times.
✓ Branch 1 taken 6419 times.
270123 ms->last_mux_dts != AV_NOPTS_VALUE) {
175 263704 int64_t max = ms->last_mux_dts + !(mux->fc->oformat->flags & AVFMT_TS_NONSTRICT);
176
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 263648 times.
263704 if (pkt->dts < max) {
177
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;
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (exit_on_error)
179 loglevel = AV_LOG_ERROR;
180 56 av_log(ost, loglevel, "Non-monotonic DTS; "
181 "previous: %"PRId64", current: %"PRId64"; ",
182 ms->last_mux_dts, pkt->dts);
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (exit_on_error) {
184 return AVERROR(EINVAL);
185 }
186
187 56 av_log(ost, loglevel, "changing to %"PRId64". This may result "
188 "in incorrect timestamps in the output file.\n",
189 max);
190
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (pkt->pts >= pkt->dts)
191 56 pkt->pts = FFMAX(pkt->pts, max);
192 56 pkt->dts = max;
193 }
194 }
195 }
196 599507 ms->last_mux_dts = pkt->dts;
197
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599507 times.
599507 if (debug_ts)
199 mux_log_debug_ts(ost, pkt);
200
201 599507 return 0;
202 }
203
204 599507 static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
205 {
206 599507 MuxStream *ms = ms_from_ost(ost);
207 599507 AVFormatContext *s = mux->fc;
208 int64_t fs;
209 uint64_t frame_num;
210 int ret;
211
212 599507 fs = filesize(s->pb);
213 599507 atomic_store(&mux->last_filesize, fs);
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599507 times.
599507 if (fs >= mux->limit_filesize) {
215 ret = AVERROR_EOF;
216 goto fail;
217 }
218
219 599507 ret = mux_fixup_ts(mux, ms, pkt);
220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599507 times.
599507 if (ret < 0)
221 goto fail;
222
223 599507 ms->data_size_mux += pkt->size;
224 599507 frame_num = atomic_fetch_add(&ost->packets_written, 1);
225
226 599507 pkt->stream_index = ost->index;
227
228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599507 times.
599507 if (ms->stats.io)
229 enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num);
230
231 599507 ret = av_interleaved_write_frame(s, pkt);
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 599507 times.
599507 if (ret < 0) {
233 av_log(ost, AV_LOG_ERROR,
234 "Error submitting a packet to the muxer: %s\n",
235 av_err2str(ret));
236 goto fail;
237 }
238
239 599507 return 0;
240 fail:
241 av_packet_unref(pkt);
242 return ret;
243 }
244
245 608747 static int sync_queue_process(Muxer *mux, MuxStream *ms, AVPacket *pkt, int *stream_eof)
246 {
247 608747 OutputFile *of = &mux->of;
248
249
2/2
✓ Branch 0 taken 967 times.
✓ Branch 1 taken 607780 times.
608747 if (ms->sq_idx_mux >= 0) {
250 967 int ret = sq_send(mux->sq_mux, ms->sq_idx_mux, SQPKT(pkt));
251
2/2
✓ Branch 0 taken 937 times.
✓ Branch 1 taken 30 times.
967 if (ret < 0) {
252
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (ret == AVERROR_EOF)
253 30 *stream_eof = 1;
254
255 30 return ret;
256 }
257
258 876 while (1) {
259 1813 ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt));
260
2/2
✓ Branch 0 taken 937 times.
✓ Branch 1 taken 876 times.
1813 if (ret < 0) {
261 /* n.b.: We forward EOF from the sync queue, terminating muxing.
262 * This assumes that if a muxing sync queue is present, then all
263 * the streams use it. That is true currently, but may change in
264 * the future, then this code needs to be revisited.
265 */
266
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 924 times.
937 return ret == AVERROR(EAGAIN) ? 0 : ret;
267 }
268
269 876 ret = write_packet(mux, of->streams[ret],
270 mux->sq_pkt);
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 876 times.
876 if (ret < 0)
272 return ret;
273 }
274
2/2
✓ Branch 0 taken 598631 times.
✓ Branch 1 taken 9149 times.
607780 } else if (pkt)
275 598631 return write_packet(mux, &ms->ost, pkt);
276
277 9149 return 0;
278 }
279
280 static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt);
281
282 /* apply the output bitstream filters */
283 609637 static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt,
284 OutputStream *ost, AVPacket *pkt, int *stream_eof)
285 {
286 609637 MuxStream *ms = ms_from_ost(ost);
287 const char *err_msg;
288 int ret;
289
290
4/4
✓ Branch 0 taken 600541 times.
✓ Branch 1 taken 9096 times.
✓ Branch 2 taken 74373 times.
✓ Branch 3 taken 526168 times.
609637 if (pkt && !ost->enc) {
291 74373 ret = of_streamcopy(&mux->of, ost, pkt);
292
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 74100 times.
74373 if (ret == AVERROR(EAGAIN))
293 273 return 0;
294
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 74032 times.
74100 else if (ret == AVERROR_EOF) {
295 68 av_packet_unref(pkt);
296 68 pkt = NULL;
297 68 *stream_eof = 1;
298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74032 times.
74032 } else if (ret < 0)
299 goto fail;
300 }
301
302 // emit heartbeat for -fix_sub_duration;
303 // we are only interested in heartbeats on on random access points.
304
4/4
✓ Branch 0 taken 600200 times.
✓ Branch 1 taken 9164 times.
✓ Branch 2 taken 560135 times.
✓ Branch 3 taken 40065 times.
609364 if (pkt && (pkt->flags & AV_PKT_FLAG_KEY)) {
305 560135 mt->fix_sub_duration_pkt->opaque = (void*)(intptr_t)PKT_OPAQUE_FIX_SUB_DURATION;
306 560135 mt->fix_sub_duration_pkt->pts = pkt->pts;
307 560135 mt->fix_sub_duration_pkt->time_base = pkt->time_base;
308
309 560135 ret = sch_mux_sub_heartbeat(mux->sch, mux->sch_idx, ms->sch_idx,
310 560135 mt->fix_sub_duration_pkt);
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 560135 times.
560135 if (ret < 0)
312 goto fail;
313 }
314
315
2/2
✓ Branch 0 taken 10786 times.
✓ Branch 1 taken 598578 times.
609364 if (ms->bsf_ctx) {
316 10786 int bsf_eof = 0;
317
318
2/2
✓ Branch 0 taken 10636 times.
✓ Branch 1 taken 150 times.
10786 if (pkt)
319 10636 av_packet_rescale_ts(pkt, pkt->time_base, ms->bsf_ctx->time_base_in);
320
321 10786 ret = av_bsf_send_packet(ms->bsf_ctx, pkt);
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10786 times.
10786 if (ret < 0) {
323 err_msg = "submitting a packet for bitstream filtering";
324 goto fail;
325 }
326
327
2/2
✓ Branch 0 taken 20807 times.
✓ Branch 1 taken 148 times.
20955 while (!bsf_eof) {
328 20807 ret = av_bsf_receive_packet(ms->bsf_ctx, ms->bsf_pkt);
329
2/2
✓ Branch 0 taken 10636 times.
✓ Branch 1 taken 10171 times.
20807 if (ret == AVERROR(EAGAIN))
330 10636 return 0;
331
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 10023 times.
10171 else if (ret == AVERROR_EOF)
332 148 bsf_eof = 1;
333
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10021 times.
10023 else if (ret < 0) {
334 2 av_log(ost, AV_LOG_ERROR,
335 "Error applying bitstream filters to a packet: %s",
336 2 av_err2str(ret));
337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (exit_on_error)
338 return ret;
339 2 continue;
340 }
341
342
2/2
✓ Branch 0 taken 10021 times.
✓ Branch 1 taken 148 times.
10169 if (!bsf_eof)
343 10021 ms->bsf_pkt->time_base = ms->bsf_ctx->time_base_out;
344
345
2/2
✓ Branch 0 taken 10021 times.
✓ Branch 1 taken 148 times.
10169 ret = sync_queue_process(mux, ms, bsf_eof ? NULL : ms->bsf_pkt, stream_eof);
346
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10167 times.
10169 if (ret < 0)
347 2 goto mux_fail;
348 }
349 148 *stream_eof = 1;
350 } else {
351 598578 ret = sync_queue_process(mux, ms, pkt, stream_eof);
352
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 598537 times.
598578 if (ret < 0)
353 41 goto mux_fail;
354 }
355
356
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 598470 times.
598685 return *stream_eof ? AVERROR_EOF : 0;
357
358 43 mux_fail:
359 43 err_msg = "submitting a packet to the muxer";
360
361 43 fail:
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret != AVERROR_EOF)
363 av_log(ost, AV_LOG_ERROR, "Error %s: %s\n", err_msg, av_err2str(ret));
364 43 return ret;
365 }
366
367 8697 static void thread_set_name(Muxer *mux)
368 {
369 char name[16];
370 8697 snprintf(name, sizeof(name), "mux%d:%s",
371 8697 mux->of.index, mux->fc->oformat->name);
372 8697 ff_thread_setname(name);
373 8697 }
374
375 8697 static void mux_thread_uninit(MuxThreadContext *mt)
376 {
377 8697 av_packet_free(&mt->pkt);
378 8697 av_packet_free(&mt->fix_sub_duration_pkt);
379
380 8697 memset(mt, 0, sizeof(*mt));
381 8697 }
382
383 8697 static int mux_thread_init(MuxThreadContext *mt)
384 {
385 8697 memset(mt, 0, sizeof(*mt));
386
387 8697 mt->pkt = av_packet_alloc();
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8697 times.
8697 if (!mt->pkt)
389 goto fail;
390
391 8697 mt->fix_sub_duration_pkt = av_packet_alloc();
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8697 times.
8697 if (!mt->fix_sub_duration_pkt)
393 goto fail;
394
395 8697 return 0;
396
397 fail:
398 mux_thread_uninit(mt);
399 return AVERROR(ENOMEM);
400 }
401
402 8697 int muxer_thread(void *arg)
403 {
404 8697 Muxer *mux = arg;
405 8697 OutputFile *of = &mux->of;
406
407 MuxThreadContext mt;
408
409 8697 int ret = 0;
410
411 8697 ret = mux_thread_init(&mt);
412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8697 times.
8697 if (ret < 0)
413 goto finish;
414
415 8697 thread_set_name(mux);
416
417 609624 while (1) {
418 OutputStream *ost;
419 618321 int stream_idx, stream_eof = 0;
420
421 618321 ret = sch_mux_receive(mux->sch, of->index, mt.pkt);
422 618321 stream_idx = mt.pkt->stream_index;
423
2/2
✓ Branch 0 taken 8684 times.
✓ Branch 1 taken 609637 times.
618321 if (stream_idx < 0) {
424 8684 av_log(mux, AV_LOG_VERBOSE, "All streams finished\n");
425 8684 ret = 0;
426 8697 break;
427 }
428
429 609637 ost = of->streams[mux->sch_stream_idx[stream_idx]];
430 609637 mt.pkt->stream_index = ost->index;
431 609637 mt.pkt->flags &= ~AV_PKT_FLAG_TRUSTED;
432
433
2/2
✓ Branch 0 taken 600541 times.
✓ Branch 1 taken 9096 times.
609637 ret = mux_packet_filter(mux, &mt, ost, ret < 0 ? NULL : mt.pkt, &stream_eof);
434 609637 av_packet_unref(mt.pkt);
435
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 609379 times.
609637 if (ret == AVERROR_EOF) {
436
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 13 times.
258 if (stream_eof) {
437 245 sch_mux_receive_finish(mux->sch, of->index, stream_idx);
438 } else {
439 13 av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n");
440 13 ret = 0;
441 13 break;
442 }
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 609379 times.
609379 } else if (ret < 0) {
444 av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n");
445 break;
446 }
447 }
448
449 8697 finish:
450 8697 mux_thread_uninit(&mt);
451
452 8697 return ret;
453 }
454
455 74373 static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt)
456 {
457 74373 MuxStream *ms = ms_from_ost(ost);
458
1/2
✓ Branch 0 taken 74373 times.
✗ Branch 1 not taken.
74373 FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL;
459
1/2
✓ Branch 0 taken 74373 times.
✗ Branch 1 not taken.
74373 int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE;
460
2/2
✓ Branch 0 taken 1073 times.
✓ Branch 1 taken 73300 times.
74373 int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
461 int64_t ts_offset;
462
463
2/2
✓ Branch 0 taken 1666 times.
✓ Branch 1 taken 72707 times.
74373 if (of->recording_time != INT64_MAX &&
464
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 1598 times.
1666 dts >= of->recording_time + start_time)
465 68 return AVERROR_EOF;
466
467
4/4
✓ Branch 0 taken 1082 times.
✓ Branch 1 taken 73223 times.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 992 times.
74305 if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) &&
468
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 !ms->copy_initial_nonkeyframes)
469 90 return AVERROR(EAGAIN);
470
471
2/2
✓ Branch 0 taken 992 times.
✓ Branch 1 taken 73223 times.
74215 if (!ms->streamcopy_started) {
472
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 992 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
992 if (!ms->copy_prior_start &&
473 (pkt->pts == AV_NOPTS_VALUE ?
474 dts < ms->ts_copy_start :
475 pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base)))
476 return AVERROR(EAGAIN);
477
478
4/4
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 805 times.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 4 times.
992 if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time)
479 183 return AVERROR(EAGAIN);
480 }
481
482 74032 ts_offset = av_rescale_q(start_time, AV_TIME_BASE_Q, pkt->time_base);
483
484
2/2
✓ Branch 0 taken 65461 times.
✓ Branch 1 taken 8571 times.
74032 if (pkt->pts != AV_NOPTS_VALUE)
485 65461 pkt->pts -= ts_offset;
486
487
2/2
✓ Branch 0 taken 8357 times.
✓ Branch 1 taken 65675 times.
74032 if (pkt->dts == AV_NOPTS_VALUE) {
488 8357 pkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, pkt->time_base);
489
2/2
✓ Branch 0 taken 53770 times.
✓ Branch 1 taken 11905 times.
65675 } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
490 53770 pkt->pts = pkt->dts - ts_offset;
491 }
492
493 74032 pkt->dts -= ts_offset;
494
495 74032 ms->streamcopy_started = 1;
496
497 74032 return 0;
498 }
499
500 int print_sdp(const char *filename);
501
502 int print_sdp(const char *filename)
503 {
504 char sdp[16384];
505 int j = 0, ret;
506 AVIOContext *sdp_pb;
507 AVFormatContext **avc;
508
509 avc = av_malloc_array(nb_output_files, sizeof(*avc));
510 if (!avc)
511 return AVERROR(ENOMEM);
512 for (int i = 0; i < nb_output_files; i++) {
513 Muxer *mux = mux_from_of(output_files[i]);
514
515 if (!strcmp(mux->fc->oformat->name, "rtp")) {
516 avc[j] = mux->fc;
517 j++;
518 }
519 }
520
521 if (!j) {
522 av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n");
523 ret = AVERROR(EINVAL);
524 goto fail;
525 }
526
527 ret = av_sdp_create(avc, j, sdp, sizeof(sdp));
528 if (ret < 0)
529 goto fail;
530
531 if (!filename) {
532 printf("SDP:\n%s\n", sdp);
533 fflush(stdout);
534 } else {
535 ret = avio_open2(&sdp_pb, filename, AVIO_FLAG_WRITE, &int_cb, NULL);
536 if (ret < 0) {
537 av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", filename);
538 goto fail;
539 }
540
541 avio_print(sdp_pb, sdp);
542 avio_closep(&sdp_pb);
543 }
544
545 fail:
546 av_freep(&avc);
547 return ret;
548 }
549
550 8697 int mux_check_init(void *arg)
551 {
552 8697 Muxer *mux = arg;
553 8697 OutputFile *of = &mux->of;
554 8697 AVFormatContext *fc = mux->fc;
555 int ret;
556
557 8697 ret = avformat_write_header(fc, &mux->opts);
558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8697 times.
8697 if (ret < 0) {
559 av_log(mux, AV_LOG_ERROR, "Could not write header (incorrect codec "
560 "parameters ?): %s\n", av_err2str(ret));
561 return ret;
562 }
563 //assert_avoptions(of->opts);
564 8697 mux->header_written = 1;
565
566 8697 av_dump_format(fc, of->index, fc->url, 1);
567 8697 atomic_fetch_add(&nb_output_dumped, 1);
568
569 8697 return 0;
570 }
571
572 9204 static int bsf_init(MuxStream *ms)
573 {
574 9204 OutputStream *ost = &ms->ost;
575 9204 AVBSFContext *ctx = ms->bsf_ctx;
576 int ret;
577
578
2/2
✓ Branch 0 taken 9054 times.
✓ Branch 1 taken 150 times.
9204 if (!ctx)
579 9054 return avcodec_parameters_copy(ost->st->codecpar, ms->par_in);
580
581 150 ret = avcodec_parameters_copy(ctx->par_in, ms->par_in);
582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
150 if (ret < 0)
583 return ret;
584
585 150 ctx->time_base_in = ost->st->time_base;
586
587 150 ret = av_bsf_init(ctx);
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
150 if (ret < 0) {
589 av_log(ms, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n",
590 ctx->filter->name);
591 return ret;
592 }
593
594 150 ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out);
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
150 if (ret < 0)
596 return ret;
597 150 ost->st->time_base = ctx->time_base_out;
598
599 150 ms->bsf_pkt = av_packet_alloc();
600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
150 if (!ms->bsf_pkt)
601 return AVERROR(ENOMEM);
602
603 150 return 0;
604 }
605
606 9204 int of_stream_init(OutputFile *of, OutputStream *ost,
607 const AVCodecContext *enc_ctx)
608 {
609 9204 Muxer *mux = mux_from_of(of);
610 9204 MuxStream *ms = ms_from_ost(ost);
611 int ret;
612
613
2/2
✓ Branch 0 taken 8371 times.
✓ Branch 1 taken 833 times.
9204 if (enc_ctx) {
614 // use upstream time base unless it has been overridden previously
615
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8367 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8371 if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0)
616 8367 ost->st->time_base = av_add_q(enc_ctx->time_base, (AVRational){0, 1});
617
618 8371 ost->st->avg_frame_rate = enc_ctx->framerate;
619 8371 ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio;
620
621 8371 ret = avcodec_parameters_from_context(ms->par_in, enc_ctx);
622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8371 times.
8371 if (ret < 0) {
623 av_log(ost, AV_LOG_FATAL,
624 "Error initializing the output stream codec parameters.\n");
625 return ret;
626 }
627 }
628
629 /* initialize bitstream filters for the output stream
630 * needs to be done here, because the codec id for streamcopy is not
631 * known until now */
632 9204 ret = bsf_init(ms);
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9204 times.
9204 if (ret < 0)
634 return ret;
635
636
2/2
✓ Branch 0 taken 6108 times.
✓ Branch 1 taken 3096 times.
9204 if (ms->stream_duration) {
637 6108 ost->st->duration = av_rescale_q(ms->stream_duration, ms->stream_duration_tb,
638 6108 ost->st->time_base);
639 }
640
641
2/2
✓ Branch 0 taken 9203 times.
✓ Branch 1 taken 1 times.
9204 if (ms->sch_idx >= 0)
642 9203 return sch_mux_stream_ready(mux->sch, of->index, ms->sch_idx);
643
644 1 return 0;
645 }
646
647 8697 static int check_written(OutputFile *of)
648 {
649 8697 int64_t total_packets_written = 0;
650 8697 int pass1_used = 1;
651 8697 int ret = 0;
652
653
2/2
✓ Branch 0 taken 9204 times.
✓ Branch 1 taken 8697 times.
17901 for (int i = 0; i < of->nb_streams; i++) {
654 9204 OutputStream *ost = of->streams[i];
655 9204 uint64_t packets_written = atomic_load(&ost->packets_written);
656
657 9204 total_packets_written += packets_written;
658
659
2/2
✓ Branch 0 taken 8371 times.
✓ Branch 1 taken 833 times.
9204 if (ost->enc &&
660
2/2
✓ Branch 0 taken 8363 times.
✓ Branch 1 taken 8 times.
8371 (ost->enc->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2))
661 != AV_CODEC_FLAG_PASS1)
662 8363 pass1_used = 0;
663
664
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 9144 times.
9204 if (!packets_written &&
665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) {
666 av_log(ost, AV_LOG_FATAL, "Empty output stream\n");
667 ret = err_merge(ret, AVERROR(EINVAL));
668 }
669 }
670
671
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 8676 times.
8697 if (!total_packets_written) {
672 21 int level = AV_LOG_WARNING;
673
674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT) {
675 ret = err_merge(ret, AVERROR(EINVAL));
676 level = AV_LOG_FATAL;
677 }
678
679
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3 times.
21 av_log(of, level, "Output file is empty, nothing was encoded%s\n",
680 pass1_used ? "" : "(check -ss / -t / -frames parameters if used)");
681 }
682
683 8697 return ret;
684 }
685
686 8697 static void mux_final_stats(Muxer *mux)
687 {
688 8697 OutputFile *of = &mux->of;
689 8697 uint64_t total_packets = 0, total_size = 0;
690 8697 uint64_t video_size = 0, audio_size = 0, subtitle_size = 0,
691 8697 extra_size = 0, other_size = 0;
692
693 8697 uint8_t overhead[16] = "unknown";
694 8697 int64_t file_size = of_filesize(of);
695
696 8697 av_log(of, AV_LOG_VERBOSE, "Output file #%d (%s):\n",
697 of->index, of->url);
698
699
2/2
✓ Branch 0 taken 9204 times.
✓ Branch 1 taken 8697 times.
17901 for (int j = 0; j < of->nb_streams; j++) {
700 9204 OutputStream *ost = of->streams[j];
701 9204 MuxStream *ms = ms_from_ost(ost);
702 9204 const AVCodecParameters *par = ost->st->codecpar;
703 9204 const enum AVMediaType type = par->codec_type;
704 9204 const uint64_t s = ms->data_size_mux;
705
706
4/4
✓ Branch 0 taken 7325 times.
✓ Branch 1 taken 1785 times.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 13 times.
9204 switch (type) {
707 7325 case AVMEDIA_TYPE_VIDEO: video_size += s; break;
708 1785 case AVMEDIA_TYPE_AUDIO: audio_size += s; break;
709 81 case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break;
710 13 default: other_size += s; break;
711 }
712
713 9204 extra_size += par->extradata_size;
714 9204 total_size += s;
715 9204 total_packets += atomic_load(&ost->packets_written);
716
717 9204 av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ",
718 of->index, j, av_get_media_type_string(type));
719
2/2
✓ Branch 0 taken 8371 times.
✓ Branch 1 taken 833 times.
9204 if (ost->enc) {
720 8371 av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded",
721 8371 ost->enc->frames_encoded);
722
2/2
✓ Branch 0 taken 1419 times.
✓ Branch 1 taken 6952 times.
8371 if (type == AVMEDIA_TYPE_AUDIO)
723 1419 av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->enc->samples_encoded);
724 8371 av_log(of, AV_LOG_VERBOSE, "; ");
725 }
726
727 9204 av_log(of, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ",
728 9204 atomic_load(&ost->packets_written), s);
729
730 9204 av_log(of, AV_LOG_VERBOSE, "\n");
731 }
732
733 8697 av_log(of, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n",
734 total_packets, total_size);
735
736
6/6
✓ Branch 0 taken 8675 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 8543 times.
✓ Branch 3 taken 132 times.
✓ Branch 4 taken 6371 times.
✓ Branch 5 taken 2172 times.
8697 if (total_size && file_size > 0 && file_size >= total_size) {
737 6371 snprintf(overhead, sizeof(overhead), "%f%%",
738 6371 100.0 * (file_size - total_size) / total_size);
739 }
740
741 8697 av_log(of, AV_LOG_INFO,
742 "video:%1.0fKiB audio:%1.0fKiB subtitle:%1.0fKiB other streams:%1.0fKiB "
743 "global headers:%1.0fKiB muxing overhead: %s\n",
744 video_size / 1024.0,
745 audio_size / 1024.0,
746 subtitle_size / 1024.0,
747 other_size / 1024.0,
748 extra_size / 1024.0,
749 overhead);
750 8697 }
751
752 8698 int of_write_trailer(OutputFile *of)
753 {
754 8698 Muxer *mux = mux_from_of(of);
755 8698 AVFormatContext *fc = mux->fc;
756 8698 int ret, mux_result = 0;
757
758
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8697 times.
8698 if (!mux->header_written) {
759 1 av_log(mux, AV_LOG_ERROR,
760 "Nothing was written into output file, because "
761 "at least one of its streams received no packets.\n");
762 1 return AVERROR(EINVAL);
763 }
764
765 8697 ret = av_write_trailer(fc);
766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8697 times.
8697 if (ret < 0) {
767 av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret));
768 mux_result = err_merge(mux_result, ret);
769 }
770
771 8697 mux->last_filesize = filesize(fc->pb);
772
773
2/2
✓ Branch 0 taken 8565 times.
✓ Branch 1 taken 132 times.
8697 if (!(fc->oformat->flags & AVFMT_NOFILE)) {
774 8565 ret = avio_closep(&fc->pb);
775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8565 times.
8565 if (ret < 0) {
776 av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret));
777 mux_result = err_merge(mux_result, ret);
778 }
779 }
780
781 8697 mux_final_stats(mux);
782
783 // check whether anything was actually written
784 8697 ret = check_written(of);
785 8697 mux_result = err_merge(mux_result, ret);
786
787 8697 return mux_result;
788 }
789
790 27627 static void enc_stats_uninit(EncStats *es)
791 {
792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27627 times.
27627 for (int i = 0; i < es->nb_components; i++)
793 av_freep(&es->components[i].str);
794 27627 av_freep(&es->components);
795
796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27627 times.
27627 if (es->lock_initialized)
797 pthread_mutex_destroy(&es->lock);
798 27627 es->lock_initialized = 0;
799 27627 }
800
801 9209 static void ost_free(OutputStream **post)
802 {
803 9209 OutputStream *ost = *post;
804 MuxStream *ms;
805
806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9209 times.
9209 if (!ost)
807 return;
808 9209 ms = ms_from_ost(ost);
809
810 9209 enc_free(&ost->enc);
811 9209 fg_free(&ost->fg_simple);
812
813
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9201 times.
9209 if (ost->logfile) {
814
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (fclose(ost->logfile))
815 av_log(ms, AV_LOG_ERROR,
816 "Error closing logfile, loss of information possible: %s\n",
817 av_err2str(AVERROR(errno)));
818 8 ost->logfile = NULL;
819 }
820
821 9209 avcodec_parameters_free(&ms->par_in);
822
823 9209 av_bsf_free(&ms->bsf_ctx);
824 9209 av_packet_free(&ms->bsf_pkt);
825
826 9209 av_packet_free(&ms->pkt);
827
828 9209 av_freep(&ost->kf.pts);
829 9209 av_expr_free(ost->kf.pexpr);
830
831 9209 av_freep(&ost->logfile_prefix);
832
833 9209 av_freep(&ost->attachment_filename);
834
835 9209 enc_stats_uninit(&ost->enc_stats_pre);
836 9209 enc_stats_uninit(&ost->enc_stats_post);
837 9209 enc_stats_uninit(&ms->stats);
838
839 9209 av_freep(post);
840 }
841
842 8703 static void fc_close(AVFormatContext **pfc)
843 {
844 8703 AVFormatContext *fc = *pfc;
845
846
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8702 times.
8703 if (!fc)
847 1 return;
848
849
2/2
✓ Branch 0 taken 8566 times.
✓ Branch 1 taken 136 times.
8702 if (!(fc->oformat->flags & AVFMT_NOFILE))
850 8566 avio_closep(&fc->pb);
851 8702 avformat_free_context(fc);
852
853 8702 *pfc = NULL;
854 }
855
856 8703 void of_free(OutputFile **pof)
857 {
858 8703 OutputFile *of = *pof;
859 Muxer *mux;
860
861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8703 times.
8703 if (!of)
862 return;
863 8703 mux = mux_from_of(of);
864
865 8703 sq_free(&mux->sq_mux);
866
867
2/2
✓ Branch 0 taken 9209 times.
✓ Branch 1 taken 8703 times.
17912 for (int i = 0; i < of->nb_streams; i++)
868 9209 ost_free(&of->streams[i]);
869 8703 av_freep(&of->streams);
870
871 8703 av_freep(&mux->sch_stream_idx);
872
873 8703 av_dict_free(&mux->opts);
874 8703 av_dict_free(&mux->enc_opts_used);
875
876 8703 av_packet_free(&mux->sq_pkt);
877
878 8703 fc_close(&mux->fc);
879
880 8703 av_freep(pof);
881 }
882
883 36539 int64_t of_filesize(OutputFile *of)
884 {
885 36539 Muxer *mux = mux_from_of(of);
886 36539 return atomic_load(&mux->last_filesize);
887 }
888