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 | 48341 | static Muxer *mux_from_of(OutputFile *of) | |
47 | { | ||
48 | 48341 | return (Muxer*)of; | |
49 | } | ||
50 | |||
51 | 479906 | static int64_t filesize(AVIOContext *pb) | |
52 | { | ||
53 | 479906 | int64_t ret = -1; | |
54 | |||
55 |
2/2✓ Branch 0 taken 470651 times.
✓ Branch 1 taken 9255 times.
|
479906 | if (pb) { |
56 | 470651 | ret = avio_size(pb); | |
57 |
2/2✓ Branch 0 taken 101659 times.
✓ Branch 1 taken 368992 times.
|
470651 | if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too |
58 | 101659 | ret = avio_tell(pb); | |
59 | } | ||
60 | |||
61 | 479906 | 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 | 473126 | static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt) | |
139 | { | ||
140 | 473126 | OutputStream *ost = &ms->ost; | |
141 | |||
142 | #if FFMPEG_OPT_VSYNC_DROP | ||
143 |
3/4✓ Branch 0 taken 125246 times.
✓ Branch 1 taken 347880 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 125246 times.
|
473126 | if (ost->type == AVMEDIA_TYPE_VIDEO && ms->ts_drop) |
144 | ✗ | pkt->pts = pkt->dts = AV_NOPTS_VALUE; | |
145 | #endif | ||
146 | |||
147 | // rescale timestamps to the stream timebase | ||
148 |
4/4✓ Branch 0 taken 346045 times.
✓ Branch 1 taken 127081 times.
✓ Branch 2 taken 48516 times.
✓ Branch 3 taken 297529 times.
|
473126 | if (ost->type == AVMEDIA_TYPE_AUDIO && !ost->enc) { |
149 | // use av_rescale_delta() for streamcopying audio, to preserve | ||
150 | // accuracy with coarse input timebases | ||
151 | 48516 | int duration = av_get_audio_frame_duration2(ost->st->codecpar, pkt->size); | |
152 | |||
153 |
2/2✓ Branch 0 taken 16456 times.
✓ Branch 1 taken 32060 times.
|
48516 | if (!duration) |
154 | 16456 | duration = ost->st->codecpar->frame_size; | |
155 | |||
156 | 97032 | pkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, | |
157 | 48516 | (AVRational){1, ost->st->codecpar->sample_rate}, duration, | |
158 | 48516 | &ms->ts_rescale_delta_last, ost->st->time_base); | |
159 | 48516 | pkt->pts = pkt->dts; | |
160 | |||
161 | 48516 | pkt->duration = av_rescale_q(pkt->duration, pkt->time_base, ost->st->time_base); | |
162 | } else | ||
163 | 424610 | av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base); | |
164 | 473126 | pkt->time_base = ost->st->time_base; | |
165 | |||
166 |
2/2✓ Branch 0 taken 212102 times.
✓ Branch 1 taken 261024 times.
|
473126 | if (!(mux->fc->oformat->flags & AVFMT_NOTIMESTAMPS)) { |
167 |
1/2✓ Branch 0 taken 212102 times.
✗ Branch 1 not taken.
|
212102 | if (pkt->dts != AV_NOPTS_VALUE && |
168 |
2/2✓ Branch 0 taken 211008 times.
✓ Branch 1 taken 1094 times.
|
212102 | pkt->pts != AV_NOPTS_VALUE && |
169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 211008 times.
|
211008 | pkt->dts > pkt->pts) { |
170 | ✗ | av_log(ost, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64", replacing by guess\n", | |
171 | pkt->dts, pkt->pts); | ||
172 | ✗ | pkt->pts = | |
173 | ✗ | pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1 | |
174 | ✗ | - FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1) | |
175 | ✗ | - FFMAX3(pkt->pts, pkt->dts, ms->last_mux_dts + 1); | |
176 | } | ||
177 |
6/6✓ Branch 0 taken 90958 times.
✓ Branch 1 taken 121144 times.
✓ Branch 2 taken 1332 times.
✓ Branch 3 taken 89626 times.
✓ Branch 4 taken 1319 times.
✓ Branch 5 taken 13 times.
|
212102 | if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) && |
178 |
1/2✓ Branch 0 taken 212089 times.
✗ Branch 1 not taken.
|
212089 | pkt->dts != AV_NOPTS_VALUE && |
179 |
2/2✓ Branch 0 taken 206487 times.
✓ Branch 1 taken 5602 times.
|
212089 | ms->last_mux_dts != AV_NOPTS_VALUE) { |
180 | 206487 | int64_t max = ms->last_mux_dts + !(mux->fc->oformat->flags & AVFMT_TS_NONSTRICT); | |
181 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 206459 times.
|
206487 | if (pkt->dts < max) { |
182 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
28 | int loglevel = max - pkt->dts > 2 || ost->type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; |
183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | if (exit_on_error) |
184 | ✗ | loglevel = AV_LOG_ERROR; | |
185 | 28 | av_log(ost, loglevel, "Non-monotonic DTS; " | |
186 | "previous: %"PRId64", current: %"PRId64"; ", | ||
187 | ms->last_mux_dts, pkt->dts); | ||
188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | if (exit_on_error) { |
189 | ✗ | return AVERROR(EINVAL); | |
190 | } | ||
191 | |||
192 | 28 | av_log(ost, loglevel, "changing to %"PRId64". This may result " | |
193 | "in incorrect timestamps in the output file.\n", | ||
194 | max); | ||
195 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (pkt->pts >= pkt->dts) |
196 | 28 | pkt->pts = FFMAX(pkt->pts, max); | |
197 | 28 | pkt->dts = max; | |
198 | } | ||
199 | } | ||
200 | } | ||
201 | 473126 | ms->last_mux_dts = pkt->dts; | |
202 | |||
203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 473126 times.
|
473126 | if (debug_ts) |
204 | ✗ | mux_log_debug_ts(ost, pkt); | |
205 | |||
206 | 473126 | return 0; | |
207 | } | ||
208 | |||
209 | 473126 | static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) | |
210 | { | ||
211 | 473126 | MuxStream *ms = ms_from_ost(ost); | |
212 | 473126 | AVFormatContext *s = mux->fc; | |
213 | int64_t fs; | ||
214 | uint64_t frame_num; | ||
215 | int ret; | ||
216 | |||
217 | 473126 | fs = filesize(s->pb); | |
218 | 473126 | atomic_store(&mux->last_filesize, fs); | |
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 473126 times.
|
473126 | if (fs >= mux->limit_filesize) { |
220 | ✗ | ret = AVERROR_EOF; | |
221 | ✗ | goto fail; | |
222 | } | ||
223 | |||
224 | 473126 | ret = mux_fixup_ts(mux, ms, pkt); | |
225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 473126 times.
|
473126 | if (ret < 0) |
226 | ✗ | goto fail; | |
227 | |||
228 | 473126 | ms->data_size_mux += pkt->size; | |
229 | 473126 | frame_num = atomic_fetch_add(&ost->packets_written, 1); | |
230 | |||
231 | 473126 | pkt->stream_index = ost->index; | |
232 | |||
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 473126 times.
|
473126 | if (ms->stats.io) |
234 | ✗ | enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num); | |
235 | |||
236 | 473126 | ret = av_interleaved_write_frame(s, pkt); | |
237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 473126 times.
|
473126 | if (ret < 0) { |
238 | ✗ | av_log(ost, AV_LOG_ERROR, | |
239 | "Error submitting a packet to the muxer: %s\n", | ||
240 | ✗ | av_err2str(ret)); | |
241 | ✗ | goto fail; | |
242 | } | ||
243 | |||
244 | 473126 | return 0; | |
245 | ✗ | fail: | |
246 | ✗ | av_packet_unref(pkt); | |
247 | ✗ | return ret; | |
248 | } | ||
249 | |||
250 | 480297 | static int sync_queue_process(Muxer *mux, MuxStream *ms, AVPacket *pkt, int *stream_eof) | |
251 | { | ||
252 | 480297 | OutputFile *of = &mux->of; | |
253 | |||
254 |
2/2✓ Branch 0 taken 827 times.
✓ Branch 1 taken 479470 times.
|
480297 | if (ms->sq_idx_mux >= 0) { |
255 | 827 | int ret = sq_send(mux->sq_mux, ms->sq_idx_mux, SQPKT(pkt)); | |
256 |
2/2✓ Branch 0 taken 805 times.
✓ Branch 1 taken 22 times.
|
827 | if (ret < 0) { |
257 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | if (ret == AVERROR_EOF) |
258 | 22 | *stream_eof = 1; | |
259 | |||
260 | 22 | return ret; | |
261 | } | ||
262 | |||
263 | 745 | while (1) { | |
264 | 1550 | ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt)); | |
265 |
2/2✓ Branch 0 taken 805 times.
✓ Branch 1 taken 745 times.
|
1550 | if (ret < 0) { |
266 | /* n.b.: We forward EOF from the sync queue, terminating muxing. | ||
267 | * This assumes that if a muxing sync queue is present, then all | ||
268 | * the streams use it. That is true currently, but may change in | ||
269 | * the future, then this code needs to be revisited. | ||
270 | */ | ||
271 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 795 times.
|
805 | return ret == AVERROR(EAGAIN) ? 0 : ret; |
272 | } | ||
273 | |||
274 | 745 | ret = write_packet(mux, of->streams[ret], | |
275 | mux->sq_pkt); | ||
276 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 745 times.
|
745 | if (ret < 0) |
277 | ✗ | return ret; | |
278 | } | ||
279 |
2/2✓ Branch 0 taken 472381 times.
✓ Branch 1 taken 7089 times.
|
479470 | } else if (pkt) |
280 | 472381 | return write_packet(mux, &ms->ost, pkt); | |
281 | |||
282 | 7089 | return 0; | |
283 | } | ||
284 | |||
285 | static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt); | ||
286 | |||
287 | /* apply the output bitstream filters */ | ||
288 | 481117 | static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt, | |
289 | OutputStream *ost, AVPacket *pkt, int *stream_eof) | ||
290 | { | ||
291 | 481117 | MuxStream *ms = ms_from_ost(ost); | |
292 | const char *err_msg; | ||
293 | int ret; | ||
294 | |||
295 |
4/4✓ Branch 0 taken 474061 times.
✓ Branch 1 taken 7056 times.
✓ Branch 2 taken 67177 times.
✓ Branch 3 taken 406884 times.
|
481117 | if (pkt && !ost->enc) { |
296 | 67177 | ret = of_streamcopy(&mux->of, ost, pkt); | |
297 |
2/2✓ Branch 0 taken 247 times.
✓ Branch 1 taken 66930 times.
|
67177 | if (ret == AVERROR(EAGAIN)) |
298 | 247 | return 0; | |
299 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 66885 times.
|
66930 | else if (ret == AVERROR_EOF) { |
300 | 45 | av_packet_unref(pkt); | |
301 | 45 | pkt = NULL; | |
302 | 45 | *stream_eof = 1; | |
303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66885 times.
|
66885 | } else if (ret < 0) |
304 | ✗ | goto fail; | |
305 | } | ||
306 | |||
307 | // emit heartbeat for -fix_sub_duration; | ||
308 | // we are only interested in heartbeats on on random access points. | ||
309 |
4/4✓ Branch 0 taken 473769 times.
✓ Branch 1 taken 7101 times.
✓ Branch 2 taken 437605 times.
✓ Branch 3 taken 36164 times.
|
480870 | if (pkt && (pkt->flags & AV_PKT_FLAG_KEY)) { |
310 | 437605 | mt->fix_sub_duration_pkt->opaque = (void*)(intptr_t)PKT_OPAQUE_FIX_SUB_DURATION; | |
311 | 437605 | mt->fix_sub_duration_pkt->pts = pkt->pts; | |
312 | 437605 | mt->fix_sub_duration_pkt->time_base = pkt->time_base; | |
313 | |||
314 | 437605 | ret = sch_mux_sub_heartbeat(mux->sch, mux->sch_idx, ms->sch_idx, | |
315 | 437605 | mt->fix_sub_duration_pkt); | |
316 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 437605 times.
|
437605 | if (ret < 0) |
317 | ✗ | goto fail; | |
318 | } | ||
319 | |||
320 |
2/2✓ Branch 0 taken 10296 times.
✓ Branch 1 taken 470574 times.
|
480870 | if (ms->bsf_ctx) { |
321 | 10296 | int bsf_eof = 0; | |
322 | |||
323 |
2/2✓ Branch 0 taken 10164 times.
✓ Branch 1 taken 132 times.
|
10296 | if (pkt) |
324 | 10164 | av_packet_rescale_ts(pkt, pkt->time_base, ms->bsf_ctx->time_base_in); | |
325 | |||
326 | 10296 | ret = av_bsf_send_packet(ms->bsf_ctx, pkt); | |
327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10296 times.
|
10296 | if (ret < 0) { |
328 | ✗ | err_msg = "submitting a packet for bitstream filtering"; | |
329 | ✗ | goto fail; | |
330 | } | ||
331 | |||
332 |
2/2✓ Branch 0 taken 19889 times.
✓ Branch 1 taken 132 times.
|
20021 | while (!bsf_eof) { |
333 | 19889 | ret = av_bsf_receive_packet(ms->bsf_ctx, ms->bsf_pkt); | |
334 |
2/2✓ Branch 0 taken 10164 times.
✓ Branch 1 taken 9725 times.
|
19889 | if (ret == AVERROR(EAGAIN)) |
335 | 10164 | return 0; | |
336 |
2/2✓ Branch 0 taken 132 times.
✓ Branch 1 taken 9593 times.
|
9725 | else if (ret == AVERROR_EOF) |
337 | 132 | bsf_eof = 1; | |
338 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9591 times.
|
9593 | else if (ret < 0) { |
339 | 2 | av_log(ost, AV_LOG_ERROR, | |
340 | "Error applying bitstream filters to a packet: %s", | ||
341 | 2 | av_err2str(ret)); | |
342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (exit_on_error) |
343 | ✗ | return ret; | |
344 | 2 | continue; | |
345 | } | ||
346 | |||
347 |
2/2✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 132 times.
|
9723 | if (!bsf_eof) |
348 | 9591 | ms->bsf_pkt->time_base = ms->bsf_ctx->time_base_out; | |
349 | |||
350 |
2/2✓ Branch 0 taken 9591 times.
✓ Branch 1 taken 132 times.
|
9723 | ret = sync_queue_process(mux, ms, bsf_eof ? NULL : ms->bsf_pkt, stream_eof); |
351 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9723 times.
|
9723 | if (ret < 0) |
352 | ✗ | goto mux_fail; | |
353 | } | ||
354 | 132 | *stream_eof = 1; | |
355 | } else { | ||
356 | 470574 | ret = sync_queue_process(mux, ms, pkt, stream_eof); | |
357 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 470542 times.
|
470574 | if (ret < 0) |
358 | 32 | goto mux_fail; | |
359 | } | ||
360 | |||
361 |
2/2✓ Branch 0 taken 176 times.
✓ Branch 1 taken 470498 times.
|
470674 | return *stream_eof ? AVERROR_EOF : 0; |
362 | |||
363 | 32 | mux_fail: | |
364 | 32 | err_msg = "submitting a packet to the muxer"; | |
365 | |||
366 | 32 | fail: | |
367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (ret != AVERROR_EOF) |
368 | ✗ | av_log(ost, AV_LOG_ERROR, "Error %s: %s\n", err_msg, av_err2str(ret)); | |
369 | 32 | return ret; | |
370 | } | ||
371 | |||
372 | 6780 | static void thread_set_name(Muxer *mux) | |
373 | { | ||
374 | char name[16]; | ||
375 | 6780 | snprintf(name, sizeof(name), "mux%d:%s", | |
376 | 6780 | mux->of.index, mux->fc->oformat->name); | |
377 | 6780 | ff_thread_setname(name); | |
378 | 6780 | } | |
379 | |||
380 | 6780 | static void mux_thread_uninit(MuxThreadContext *mt) | |
381 | { | ||
382 | 6780 | av_packet_free(&mt->pkt); | |
383 | 6780 | av_packet_free(&mt->fix_sub_duration_pkt); | |
384 | |||
385 | 6780 | memset(mt, 0, sizeof(*mt)); | |
386 | 6780 | } | |
387 | |||
388 | 6780 | static int mux_thread_init(MuxThreadContext *mt) | |
389 | { | ||
390 | 6780 | memset(mt, 0, sizeof(*mt)); | |
391 | |||
392 | 6780 | mt->pkt = av_packet_alloc(); | |
393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!mt->pkt) |
394 | ✗ | goto fail; | |
395 | |||
396 | 6780 | mt->fix_sub_duration_pkt = av_packet_alloc(); | |
397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!mt->fix_sub_duration_pkt) |
398 | ✗ | goto fail; | |
399 | |||
400 | 6780 | return 0; | |
401 | |||
402 | ✗ | fail: | |
403 | ✗ | mux_thread_uninit(mt); | |
404 | ✗ | return AVERROR(ENOMEM); | |
405 | } | ||
406 | |||
407 | 6780 | int muxer_thread(void *arg) | |
408 | { | ||
409 | 6780 | Muxer *mux = arg; | |
410 | 6780 | OutputFile *of = &mux->of; | |
411 | |||
412 | MuxThreadContext mt; | ||
413 | |||
414 | 6780 | int ret = 0; | |
415 | |||
416 | 6780 | ret = mux_thread_init(&mt); | |
417 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (ret < 0) |
418 | ✗ | goto finish; | |
419 | |||
420 | 6780 | thread_set_name(mux); | |
421 | |||
422 | 481107 | while (1) { | |
423 | OutputStream *ost; | ||
424 | 487887 | int stream_idx, stream_eof = 0; | |
425 | |||
426 | 487887 | ret = sch_mux_receive(mux->sch, of->index, mt.pkt); | |
427 | 487887 | stream_idx = mt.pkt->stream_index; | |
428 |
2/2✓ Branch 0 taken 6770 times.
✓ Branch 1 taken 481117 times.
|
487887 | if (stream_idx < 0) { |
429 | 6770 | av_log(mux, AV_LOG_VERBOSE, "All streams finished\n"); | |
430 | 6770 | ret = 0; | |
431 | 6780 | break; | |
432 | } | ||
433 | |||
434 | 481117 | ost = of->streams[mux->sch_stream_idx[stream_idx]]; | |
435 | 481117 | mt.pkt->stream_index = ost->index; | |
436 | 481117 | mt.pkt->flags &= ~AV_PKT_FLAG_TRUSTED; | |
437 | |||
438 |
2/2✓ Branch 0 taken 474061 times.
✓ Branch 1 taken 7056 times.
|
481117 | ret = mux_packet_filter(mux, &mt, ost, ret < 0 ? NULL : mt.pkt, &stream_eof); |
439 | 481117 | av_packet_unref(mt.pkt); | |
440 |
2/2✓ Branch 0 taken 208 times.
✓ Branch 1 taken 480909 times.
|
481117 | if (ret == AVERROR_EOF) { |
441 |
2/2✓ Branch 0 taken 198 times.
✓ Branch 1 taken 10 times.
|
208 | if (stream_eof) { |
442 | 198 | sch_mux_receive_finish(mux->sch, of->index, stream_idx); | |
443 | } else { | ||
444 | 10 | av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n"); | |
445 | 10 | ret = 0; | |
446 | 10 | break; | |
447 | } | ||
448 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 480909 times.
|
480909 | } else if (ret < 0) { |
449 | ✗ | av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n"); | |
450 | ✗ | break; | |
451 | } | ||
452 | } | ||
453 | |||
454 | 6780 | finish: | |
455 | 6780 | mux_thread_uninit(&mt); | |
456 | |||
457 | 6780 | return ret; | |
458 | } | ||
459 | |||
460 | 67177 | static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt) | |
461 | { | ||
462 | 67177 | MuxStream *ms = ms_from_ost(ost); | |
463 |
1/2✓ Branch 0 taken 67177 times.
✗ Branch 1 not taken.
|
67177 | FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL; |
464 |
1/2✓ Branch 0 taken 67177 times.
✗ Branch 1 not taken.
|
67177 | int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE; |
465 |
2/2✓ Branch 0 taken 1073 times.
✓ Branch 1 taken 66104 times.
|
67177 | int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; |
466 | int64_t ts_offset; | ||
467 | |||
468 |
2/2✓ Branch 0 taken 1341 times.
✓ Branch 1 taken 65836 times.
|
67177 | if (of->recording_time != INT64_MAX && |
469 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1296 times.
|
1341 | dts >= of->recording_time + start_time) |
470 | 45 | return AVERROR_EOF; | |
471 | |||
472 |
4/4✓ Branch 0 taken 872 times.
✓ Branch 1 taken 66260 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 808 times.
|
67132 | if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && |
473 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | !ms->copy_initial_nonkeyframes) |
474 | 64 | return AVERROR(EAGAIN); | |
475 | |||
476 |
2/2✓ Branch 0 taken 808 times.
✓ Branch 1 taken 66260 times.
|
67068 | if (!ms->streamcopy_started) { |
477 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 808 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
808 | if (!ms->copy_prior_start && |
478 | ✗ | (pkt->pts == AV_NOPTS_VALUE ? | |
479 | ✗ | dts < ms->ts_copy_start : | |
480 | ✗ | pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) | |
481 | ✗ | return AVERROR(EAGAIN); | |
482 | |||
483 |
4/4✓ Branch 0 taken 187 times.
✓ Branch 1 taken 621 times.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 4 times.
|
808 | if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) |
484 | 183 | return AVERROR(EAGAIN); | |
485 | } | ||
486 | |||
487 | 66885 | ts_offset = av_rescale_q(start_time, AV_TIME_BASE_Q, pkt->time_base); | |
488 | |||
489 |
2/2✓ Branch 0 taken 57525 times.
✓ Branch 1 taken 9360 times.
|
66885 | if (pkt->pts != AV_NOPTS_VALUE) |
490 | 57525 | pkt->pts -= ts_offset; | |
491 | |||
492 |
2/2✓ Branch 0 taken 9126 times.
✓ Branch 1 taken 57759 times.
|
66885 | if (pkt->dts == AV_NOPTS_VALUE) { |
493 | 9126 | pkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, pkt->time_base); | |
494 |
2/2✓ Branch 0 taken 47365 times.
✓ Branch 1 taken 10394 times.
|
57759 | } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
495 | 47365 | pkt->pts = pkt->dts - ts_offset; | |
496 | } | ||
497 | |||
498 | 66885 | pkt->dts -= ts_offset; | |
499 | |||
500 | 66885 | ms->streamcopy_started = 1; | |
501 | |||
502 | 66885 | return 0; | |
503 | } | ||
504 | |||
505 | int print_sdp(const char *filename); | ||
506 | |||
507 | ✗ | int print_sdp(const char *filename) | |
508 | { | ||
509 | char sdp[16384]; | ||
510 | ✗ | int j = 0, ret; | |
511 | AVIOContext *sdp_pb; | ||
512 | AVFormatContext **avc; | ||
513 | |||
514 | ✗ | avc = av_malloc_array(nb_output_files, sizeof(*avc)); | |
515 | ✗ | if (!avc) | |
516 | ✗ | return AVERROR(ENOMEM); | |
517 | ✗ | for (int i = 0; i < nb_output_files; i++) { | |
518 | ✗ | Muxer *mux = mux_from_of(output_files[i]); | |
519 | |||
520 | ✗ | if (!strcmp(mux->fc->oformat->name, "rtp")) { | |
521 | ✗ | avc[j] = mux->fc; | |
522 | ✗ | j++; | |
523 | } | ||
524 | } | ||
525 | |||
526 | ✗ | if (!j) { | |
527 | ✗ | av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n"); | |
528 | ✗ | ret = AVERROR(EINVAL); | |
529 | ✗ | goto fail; | |
530 | } | ||
531 | |||
532 | ✗ | ret = av_sdp_create(avc, j, sdp, sizeof(sdp)); | |
533 | ✗ | if (ret < 0) | |
534 | ✗ | goto fail; | |
535 | |||
536 | ✗ | if (!filename) { | |
537 | ✗ | printf("SDP:\n%s\n", sdp); | |
538 | ✗ | fflush(stdout); | |
539 | } else { | ||
540 | ✗ | ret = avio_open2(&sdp_pb, filename, AVIO_FLAG_WRITE, &int_cb, NULL); | |
541 | ✗ | if (ret < 0) { | |
542 | ✗ | av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", filename); | |
543 | ✗ | goto fail; | |
544 | } | ||
545 | |||
546 | ✗ | avio_print(sdp_pb, sdp); | |
547 | ✗ | avio_closep(&sdp_pb); | |
548 | } | ||
549 | |||
550 | ✗ | fail: | |
551 | ✗ | av_freep(&avc); | |
552 | ✗ | return ret; | |
553 | } | ||
554 | |||
555 | 6780 | int mux_check_init(void *arg) | |
556 | { | ||
557 | 6780 | Muxer *mux = arg; | |
558 | 6780 | OutputFile *of = &mux->of; | |
559 | 6780 | AVFormatContext *fc = mux->fc; | |
560 | int ret; | ||
561 | |||
562 | 6780 | ret = avformat_write_header(fc, &mux->opts); | |
563 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (ret < 0) { |
564 | ✗ | av_log(mux, AV_LOG_ERROR, "Could not write header (incorrect codec " | |
565 | ✗ | "parameters ?): %s\n", av_err2str(ret)); | |
566 | ✗ | return ret; | |
567 | } | ||
568 | //assert_avoptions(of->opts); | ||
569 | 6780 | mux->header_written = 1; | |
570 | |||
571 | 6780 | av_dump_format(fc, of->index, fc->url, 1); | |
572 | 6780 | atomic_fetch_add(&nb_output_dumped, 1); | |
573 | |||
574 | 6780 | return 0; | |
575 | } | ||
576 | |||
577 | 7133 | static int bsf_init(MuxStream *ms) | |
578 | { | ||
579 | 7133 | OutputStream *ost = &ms->ost; | |
580 | 7133 | AVBSFContext *ctx = ms->bsf_ctx; | |
581 | int ret; | ||
582 | |||
583 |
2/2✓ Branch 0 taken 7001 times.
✓ Branch 1 taken 132 times.
|
7133 | if (!ctx) |
584 | 7001 | return avcodec_parameters_copy(ost->st->codecpar, ost->par_in); | |
585 | |||
586 | 132 | ret = avcodec_parameters_copy(ctx->par_in, ost->par_in); | |
587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ret < 0) |
588 | ✗ | return ret; | |
589 | |||
590 | 132 | ctx->time_base_in = ost->st->time_base; | |
591 | |||
592 | 132 | ret = av_bsf_init(ctx); | |
593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ret < 0) { |
594 | ✗ | av_log(ms, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", | |
595 | ✗ | ctx->filter->name); | |
596 | ✗ | return ret; | |
597 | } | ||
598 | |||
599 | 132 | ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); | |
600 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ret < 0) |
601 | ✗ | return ret; | |
602 | 132 | ost->st->time_base = ctx->time_base_out; | |
603 | |||
604 | 132 | ms->bsf_pkt = av_packet_alloc(); | |
605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (!ms->bsf_pkt) |
606 | ✗ | return AVERROR(ENOMEM); | |
607 | |||
608 | 132 | return 0; | |
609 | } | ||
610 | |||
611 | 7133 | int of_stream_init(OutputFile *of, OutputStream *ost) | |
612 | { | ||
613 | 7133 | Muxer *mux = mux_from_of(of); | |
614 | 7133 | MuxStream *ms = ms_from_ost(ost); | |
615 | int ret; | ||
616 | |||
617 | /* initialize bitstream filters for the output stream | ||
618 | * needs to be done here, because the codec id for streamcopy is not | ||
619 | * known until now */ | ||
620 | 7133 | ret = bsf_init(ms); | |
621 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (ret < 0) |
622 | ✗ | return ret; | |
623 | |||
624 |
2/2✓ Branch 0 taken 5446 times.
✓ Branch 1 taken 1687 times.
|
7133 | if (ms->stream_duration) { |
625 | 5446 | ost->st->duration = av_rescale_q(ms->stream_duration, ms->stream_duration_tb, | |
626 | 5446 | ost->st->time_base); | |
627 | } | ||
628 | |||
629 |
2/2✓ Branch 0 taken 7132 times.
✓ Branch 1 taken 1 times.
|
7133 | if (ms->sch_idx >= 0) |
630 | 7132 | return sch_mux_stream_ready(mux->sch, of->index, ms->sch_idx); | |
631 | |||
632 | 1 | return 0; | |
633 | } | ||
634 | |||
635 | 6780 | static int check_written(OutputFile *of) | |
636 | { | ||
637 | 6780 | int64_t total_packets_written = 0; | |
638 | 6780 | int pass1_used = 1; | |
639 | 6780 | int ret = 0; | |
640 | |||
641 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (int i = 0; i < of->nb_streams; i++) { |
642 | 7133 | OutputStream *ost = of->streams[i]; | |
643 | 7133 | uint64_t packets_written = atomic_load(&ost->packets_written); | |
644 | |||
645 | 7133 | total_packets_written += packets_written; | |
646 | |||
647 |
2/2✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
|
7133 | if (ost->enc_ctx && |
648 |
2/2✓ Branch 0 taken 6483 times.
✓ Branch 1 taken 4 times.
|
6487 | (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) |
649 | != AV_CODEC_FLAG_PASS1) | ||
650 | 6483 | pass1_used = 0; | |
651 | |||
652 |
2/2✓ Branch 0 taken 47 times.
✓ Branch 1 taken 7086 times.
|
7133 | if (!packets_written && |
653 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
|
47 | (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { |
654 | ✗ | av_log(ost, AV_LOG_FATAL, "Empty output stream\n"); | |
655 | ✗ | ret = err_merge(ret, AVERROR(EINVAL)); | |
656 | } | ||
657 | } | ||
658 | |||
659 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6766 times.
|
6780 | if (!total_packets_written) { |
660 | 14 | int level = AV_LOG_WARNING; | |
661 | |||
662 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT) { |
663 | ✗ | ret = err_merge(ret, AVERROR(EINVAL)); | |
664 | ✗ | level = AV_LOG_FATAL; | |
665 | } | ||
666 | |||
667 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
|
14 | av_log(of, level, "Output file is empty, nothing was encoded%s\n", |
668 | pass1_used ? "" : "(check -ss / -t / -frames parameters if used)"); | ||
669 | } | ||
670 | |||
671 | 6780 | return ret; | |
672 | } | ||
673 | |||
674 | 6780 | static void mux_final_stats(Muxer *mux) | |
675 | { | ||
676 | 6780 | OutputFile *of = &mux->of; | |
677 | 6780 | uint64_t total_packets = 0, total_size = 0; | |
678 | 6780 | uint64_t video_size = 0, audio_size = 0, subtitle_size = 0, | |
679 | 6780 | extra_size = 0, other_size = 0; | |
680 | |||
681 | 6780 | uint8_t overhead[16] = "unknown"; | |
682 | 6780 | int64_t file_size = of_filesize(of); | |
683 | |||
684 | 6780 | av_log(of, AV_LOG_VERBOSE, "Output file #%d (%s):\n", | |
685 | of->index, of->url); | ||
686 | |||
687 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (int j = 0; j < of->nb_streams; j++) { |
688 | 7133 | OutputStream *ost = of->streams[j]; | |
689 | 7133 | MuxStream *ms = ms_from_ost(ost); | |
690 | 7133 | const AVCodecParameters *par = ost->st->codecpar; | |
691 | 7133 | const enum AVMediaType type = par->codec_type; | |
692 | 7133 | const uint64_t s = ms->data_size_mux; | |
693 | |||
694 |
4/4✓ Branch 0 taken 5539 times.
✓ Branch 1 taken 1512 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 11 times.
|
7133 | switch (type) { |
695 | 5539 | case AVMEDIA_TYPE_VIDEO: video_size += s; break; | |
696 | 1512 | case AVMEDIA_TYPE_AUDIO: audio_size += s; break; | |
697 | 71 | case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break; | |
698 | 11 | default: other_size += s; break; | |
699 | } | ||
700 | |||
701 | 7133 | extra_size += par->extradata_size; | |
702 | 7133 | total_size += s; | |
703 | 7133 | total_packets += atomic_load(&ost->packets_written); | |
704 | |||
705 | 7133 | av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", | |
706 | of->index, j, av_get_media_type_string(type)); | ||
707 |
2/2✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
|
7133 | if (ost->enc) { |
708 | 6487 | av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", | |
709 | ost->frames_encoded); | ||
710 |
2/2✓ Branch 0 taken 1247 times.
✓ Branch 1 taken 5240 times.
|
6487 | if (type == AVMEDIA_TYPE_AUDIO) |
711 | 1247 | av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); | |
712 | 6487 | av_log(of, AV_LOG_VERBOSE, "; "); | |
713 | } | ||
714 | |||
715 | 7133 | av_log(of, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", | |
716 | 7133 | atomic_load(&ost->packets_written), s); | |
717 | |||
718 | 7133 | av_log(of, AV_LOG_VERBOSE, "\n"); | |
719 | } | ||
720 | |||
721 | 6780 | av_log(of, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", | |
722 | total_packets, total_size); | ||
723 | |||
724 |
6/6✓ Branch 0 taken 6766 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 6675 times.
✓ Branch 3 taken 91 times.
✓ Branch 4 taken 4656 times.
✓ Branch 5 taken 2019 times.
|
6780 | if (total_size && file_size > 0 && file_size >= total_size) { |
725 | 4656 | snprintf(overhead, sizeof(overhead), "%f%%", | |
726 | 4656 | 100.0 * (file_size - total_size) / total_size); | |
727 | } | ||
728 | |||
729 | 6780 | av_log(of, AV_LOG_INFO, | |
730 | "video:%1.0fKiB audio:%1.0fKiB subtitle:%1.0fKiB other streams:%1.0fKiB " | ||
731 | "global headers:%1.0fKiB muxing overhead: %s\n", | ||
732 | video_size / 1024.0, | ||
733 | audio_size / 1024.0, | ||
734 | subtitle_size / 1024.0, | ||
735 | other_size / 1024.0, | ||
736 | extra_size / 1024.0, | ||
737 | overhead); | ||
738 | 6780 | } | |
739 | |||
740 | 6780 | int of_write_trailer(OutputFile *of) | |
741 | { | ||
742 | 6780 | Muxer *mux = mux_from_of(of); | |
743 | 6780 | AVFormatContext *fc = mux->fc; | |
744 | 6780 | int ret, mux_result = 0; | |
745 | |||
746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!mux->header_written) { |
747 | ✗ | av_log(mux, AV_LOG_ERROR, | |
748 | "Nothing was written into output file, because " | ||
749 | "at least one of its streams received no packets.\n"); | ||
750 | ✗ | return AVERROR(EINVAL); | |
751 | } | ||
752 | |||
753 | 6780 | ret = av_write_trailer(fc); | |
754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (ret < 0) { |
755 | ✗ | av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret)); | |
756 | ✗ | mux_result = err_merge(mux_result, ret); | |
757 | } | ||
758 | |||
759 | 6780 | mux->last_filesize = filesize(fc->pb); | |
760 | |||
761 |
2/2✓ Branch 0 taken 6689 times.
✓ Branch 1 taken 91 times.
|
6780 | if (!(fc->oformat->flags & AVFMT_NOFILE)) { |
762 | 6689 | ret = avio_closep(&fc->pb); | |
763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6689 times.
|
6689 | if (ret < 0) { |
764 | ✗ | av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret)); | |
765 | ✗ | mux_result = err_merge(mux_result, ret); | |
766 | } | ||
767 | } | ||
768 | |||
769 | 6780 | mux_final_stats(mux); | |
770 | |||
771 | // check whether anything was actually written | ||
772 | 6780 | ret = check_written(of); | |
773 | 6780 | mux_result = err_merge(mux_result, ret); | |
774 | |||
775 | 6780 | return mux_result; | |
776 | } | ||
777 | |||
778 | 21399 | static void enc_stats_uninit(EncStats *es) | |
779 | { | ||
780 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21399 times.
|
21399 | for (int i = 0; i < es->nb_components; i++) |
781 | ✗ | av_freep(&es->components[i].str); | |
782 | 21399 | av_freep(&es->components); | |
783 | |||
784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21399 times.
|
21399 | if (es->lock_initialized) |
785 | ✗ | pthread_mutex_destroy(&es->lock); | |
786 | 21399 | es->lock_initialized = 0; | |
787 | 21399 | } | |
788 | |||
789 | 7133 | static void ost_free(OutputStream **post) | |
790 | { | ||
791 | 7133 | OutputStream *ost = *post; | |
792 | MuxStream *ms; | ||
793 | |||
794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7133 times.
|
7133 | if (!ost) |
795 | ✗ | return; | |
796 | 7133 | ms = ms_from_ost(ost); | |
797 | |||
798 | 7133 | enc_free(&ost->enc); | |
799 | 7133 | fg_free(&ost->fg_simple); | |
800 | |||
801 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7129 times.
|
7133 | if (ost->logfile) { |
802 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (fclose(ost->logfile)) |
803 | ✗ | av_log(ms, AV_LOG_ERROR, | |
804 | "Error closing logfile, loss of information possible: %s\n", | ||
805 | ✗ | av_err2str(AVERROR(errno))); | |
806 | 4 | ost->logfile = NULL; | |
807 | } | ||
808 | |||
809 | 7133 | avcodec_parameters_free(&ost->par_in); | |
810 | |||
811 | 7133 | av_bsf_free(&ms->bsf_ctx); | |
812 | 7133 | av_packet_free(&ms->bsf_pkt); | |
813 | |||
814 | 7133 | av_packet_free(&ms->pkt); | |
815 | |||
816 | 7133 | av_freep(&ost->kf.pts); | |
817 | 7133 | av_expr_free(ost->kf.pexpr); | |
818 | |||
819 | 7133 | av_freep(&ost->logfile_prefix); | |
820 | |||
821 | 7133 | av_freep(&ost->attachment_filename); | |
822 | |||
823 |
2/2✓ Branch 0 taken 6487 times.
✓ Branch 1 taken 646 times.
|
7133 | if (ost->enc_ctx) |
824 | 6487 | av_freep(&ost->enc_ctx->stats_in); | |
825 | 7133 | avcodec_free_context(&ost->enc_ctx); | |
826 | |||
827 | 7133 | enc_stats_uninit(&ost->enc_stats_pre); | |
828 | 7133 | enc_stats_uninit(&ost->enc_stats_post); | |
829 | 7133 | enc_stats_uninit(&ms->stats); | |
830 | |||
831 | 7133 | av_freep(post); | |
832 | } | ||
833 | |||
834 | 6780 | static void fc_close(AVFormatContext **pfc) | |
835 | { | ||
836 | 6780 | AVFormatContext *fc = *pfc; | |
837 | |||
838 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!fc) |
839 | ✗ | return; | |
840 | |||
841 |
2/2✓ Branch 0 taken 6689 times.
✓ Branch 1 taken 91 times.
|
6780 | if (!(fc->oformat->flags & AVFMT_NOFILE)) |
842 | 6689 | avio_closep(&fc->pb); | |
843 | 6780 | avformat_free_context(fc); | |
844 | |||
845 | 6780 | *pfc = NULL; | |
846 | } | ||
847 | |||
848 | 6780 | void of_free(OutputFile **pof) | |
849 | { | ||
850 | 6780 | OutputFile *of = *pof; | |
851 | Muxer *mux; | ||
852 | |||
853 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6780 times.
|
6780 | if (!of) |
854 | ✗ | return; | |
855 | 6780 | mux = mux_from_of(of); | |
856 | |||
857 | 6780 | sq_free(&mux->sq_mux); | |
858 | |||
859 |
2/2✓ Branch 0 taken 7133 times.
✓ Branch 1 taken 6780 times.
|
13913 | for (int i = 0; i < of->nb_streams; i++) |
860 | 7133 | ost_free(&of->streams[i]); | |
861 | 6780 | av_freep(&of->streams); | |
862 | |||
863 | 6780 | av_freep(&mux->sch_stream_idx); | |
864 | |||
865 | 6780 | av_dict_free(&mux->opts); | |
866 | 6780 | av_dict_free(&mux->enc_opts_used); | |
867 | |||
868 | 6780 | av_packet_free(&mux->sq_pkt); | |
869 | |||
870 | 6780 | fc_close(&mux->fc); | |
871 | |||
872 | 6780 | av_freep(pof); | |
873 | } | ||
874 | |||
875 | 27648 | int64_t of_filesize(OutputFile *of) | |
876 | { | ||
877 | 27648 | Muxer *mux = mux_from_of(of); | |
878 | 27648 | return atomic_load(&mux->last_filesize); | |
879 | } | ||
880 |