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 | 56398 | static Muxer *mux_from_of(OutputFile *of) | |
47 | { | ||
48 | 56398 | return (Muxer*)of; | |
49 | } | ||
50 | |||
51 | 504229 | static int64_t filesize(AVIOContext *pb) | |
52 | { | ||
53 | 504229 | int64_t ret = -1; | |
54 | |||
55 |
2/2✓ Branch 0 taken 494962 times.
✓ Branch 1 taken 9267 times.
|
504229 | if (pb) { |
56 | 494962 | ret = avio_size(pb); | |
57 |
2/2✓ Branch 0 taken 102779 times.
✓ Branch 1 taken 392183 times.
|
494962 | if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too |
58 | 102779 | ret = avio_tell(pb); | |
59 | } | ||
60 | |||
61 | 504229 | 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 | 496313 | static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt) | |
139 | { | ||
140 | 496313 | OutputStream *ost = &ms->ost; | |
141 | |||
142 | #if FFMPEG_OPT_VSYNC_DROP | ||
143 |
3/4✓ Branch 0 taken 148218 times.
✓ Branch 1 taken 348095 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 148218 times.
|
496313 | 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 346260 times.
✓ Branch 1 taken 150053 times.
✓ Branch 2 taken 48588 times.
✓ Branch 3 taken 297672 times.
|
496313 | 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 | 48588 | int duration = av_get_audio_frame_duration2(ost->st->codecpar, pkt->size); | |
152 | |||
153 |
2/2✓ Branch 0 taken 16456 times.
✓ Branch 1 taken 32132 times.
|
48588 | if (!duration) |
154 | 16456 | duration = ost->st->codecpar->frame_size; | |
155 | |||
156 | 97176 | pkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, | |
157 | 48588 | (AVRational){1, ost->st->codecpar->sample_rate}, duration, | |
158 | 48588 | &ms->ts_rescale_delta_last, ost->st->time_base); | |
159 | 48588 | pkt->pts = pkt->dts; | |
160 | |||
161 | 48588 | pkt->duration = av_rescale_q(pkt->duration, pkt->time_base, ost->st->time_base); | |
162 | } else | ||
163 | 447725 | av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base); | |
164 | 496313 | pkt->time_base = ost->st->time_base; | |
165 | |||
166 |
2/2✓ Branch 0 taken 215465 times.
✓ Branch 1 taken 280848 times.
|
496313 | if (!(mux->fc->oformat->flags & AVFMT_NOTIMESTAMPS)) { |
167 |
1/2✓ Branch 0 taken 215465 times.
✗ Branch 1 not taken.
|
215465 | if (pkt->dts != AV_NOPTS_VALUE && |
168 |
2/2✓ Branch 0 taken 214371 times.
✓ Branch 1 taken 1094 times.
|
215465 | pkt->pts != AV_NOPTS_VALUE && |
169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 214371 times.
|
214371 | 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 94106 times.
✓ Branch 1 taken 121359 times.
✓ Branch 2 taken 1332 times.
✓ Branch 3 taken 92774 times.
✓ Branch 4 taken 1319 times.
✓ Branch 5 taken 13 times.
|
215465 | if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) && |
178 |
1/2✓ Branch 0 taken 215452 times.
✗ Branch 1 not taken.
|
215452 | pkt->dts != AV_NOPTS_VALUE && |
179 |
2/2✓ Branch 0 taken 209423 times.
✓ Branch 1 taken 6029 times.
|
215452 | ms->last_mux_dts != AV_NOPTS_VALUE) { |
180 | 209423 | 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 209395 times.
|
209423 | 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 | 496313 | ms->last_mux_dts = pkt->dts; | |
202 | |||
203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 496313 times.
|
496313 | if (debug_ts) |
204 | ✗ | mux_log_debug_ts(ost, pkt); | |
205 | |||
206 | 496313 | return 0; | |
207 | } | ||
208 | |||
209 | 496313 | static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) | |
210 | { | ||
211 | 496313 | MuxStream *ms = ms_from_ost(ost); | |
212 | 496313 | AVFormatContext *s = mux->fc; | |
213 | int64_t fs; | ||
214 | uint64_t frame_num; | ||
215 | int ret; | ||
216 | |||
217 | 496313 | fs = filesize(s->pb); | |
218 | 496313 | atomic_store(&mux->last_filesize, fs); | |
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 496313 times.
|
496313 | if (fs >= mux->limit_filesize) { |
220 | ✗ | ret = AVERROR_EOF; | |
221 | ✗ | goto fail; | |
222 | } | ||
223 | |||
224 | 496313 | ret = mux_fixup_ts(mux, ms, pkt); | |
225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 496313 times.
|
496313 | if (ret < 0) |
226 | ✗ | goto fail; | |
227 | |||
228 | 496313 | ms->data_size_mux += pkt->size; | |
229 | 496313 | frame_num = atomic_fetch_add(&ost->packets_written, 1); | |
230 | |||
231 | 496313 | pkt->stream_index = ost->index; | |
232 | |||
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 496313 times.
|
496313 | if (ms->stats.io) |
234 | ✗ | enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num); | |
235 | |||
236 | 496313 | ret = av_interleaved_write_frame(s, pkt); | |
237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 496313 times.
|
496313 | 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 | 496313 | return 0; | |
245 | ✗ | fail: | |
246 | ✗ | av_packet_unref(pkt); | |
247 | ✗ | return ret; | |
248 | } | ||
249 | |||
250 | 504707 | static int sync_queue_process(Muxer *mux, MuxStream *ms, AVPacket *pkt, int *stream_eof) | |
251 | { | ||
252 | 504707 | OutputFile *of = &mux->of; | |
253 | |||
254 |
2/2✓ Branch 0 taken 878 times.
✓ Branch 1 taken 503829 times.
|
504707 | if (ms->sq_idx_mux >= 0) { |
255 | 878 | int ret = sq_send(mux->sq_mux, ms->sq_idx_mux, SQPKT(pkt)); | |
256 |
2/2✓ Branch 0 taken 855 times.
✓ Branch 1 taken 23 times.
|
878 | if (ret < 0) { |
257 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | if (ret == AVERROR_EOF) |
258 | 23 | *stream_eof = 1; | |
259 | |||
260 | 23 | return ret; | |
261 | } | ||
262 | |||
263 | 795 | while (1) { | |
264 | 1650 | ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt)); | |
265 |
2/2✓ Branch 0 taken 855 times.
✓ Branch 1 taken 795 times.
|
1650 | 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 11 times.
✓ Branch 1 taken 844 times.
|
855 | return ret == AVERROR(EAGAIN) ? 0 : ret; |
272 | } | ||
273 | |||
274 | 795 | ret = write_packet(mux, of->streams[ret], | |
275 | mux->sq_pkt); | ||
276 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 795 times.
|
795 | if (ret < 0) |
277 | ✗ | return ret; | |
278 | } | ||
279 |
2/2✓ Branch 0 taken 495518 times.
✓ Branch 1 taken 8311 times.
|
503829 | } else if (pkt) |
280 | 495518 | return write_packet(mux, &ms->ost, pkt); | |
281 | |||
282 | 8311 | return 0; | |
283 | } | ||
284 | |||
285 | static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt); | ||
286 | |||
287 | /* apply the output bitstream filters */ | ||
288 | 505557 | static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt, | |
289 | OutputStream *ost, AVPacket *pkt, int *stream_eof) | ||
290 | { | ||
291 | 505557 | MuxStream *ms = ms_from_ost(ost); | |
292 | const char *err_msg; | ||
293 | int ret; | ||
294 | |||
295 |
4/4✓ Branch 0 taken 497278 times.
✓ Branch 1 taken 8279 times.
✓ Branch 2 taken 67431 times.
✓ Branch 3 taken 429847 times.
|
505557 | if (pkt && !ost->enc) { |
296 | 67431 | ret = of_streamcopy(&mux->of, ost, pkt); | |
297 |
2/2✓ Branch 0 taken 247 times.
✓ Branch 1 taken 67184 times.
|
67431 | if (ret == AVERROR(EAGAIN)) |
298 | 247 | return 0; | |
299 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 67139 times.
|
67184 | 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 67139 times.
|
67139 | } 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 496986 times.
✓ Branch 1 taken 8324 times.
✓ Branch 2 taken 460067 times.
✓ Branch 3 taken 36919 times.
|
505310 | if (pkt && (pkt->flags & AV_PKT_FLAG_KEY)) { |
310 | 460067 | mt->fix_sub_duration_pkt->opaque = (void*)(intptr_t)PKT_OPAQUE_FIX_SUB_DURATION; | |
311 | 460067 | mt->fix_sub_duration_pkt->pts = pkt->pts; | |
312 | 460067 | mt->fix_sub_duration_pkt->time_base = pkt->time_base; | |
313 | |||
314 | 460067 | ret = sch_mux_sub_heartbeat(mux->sch, mux->sch_idx, ms->sch_idx, | |
315 | 460067 | mt->fix_sub_duration_pkt); | |
316 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 460067 times.
|
460067 | if (ret < 0) |
317 | ✗ | goto fail; | |
318 | } | ||
319 | |||
320 |
2/2✓ Branch 0 taken 10376 times.
✓ Branch 1 taken 494934 times.
|
505310 | if (ms->bsf_ctx) { |
321 | 10376 | int bsf_eof = 0; | |
322 | |||
323 |
2/2✓ Branch 0 taken 10243 times.
✓ Branch 1 taken 133 times.
|
10376 | if (pkt) |
324 | 10243 | av_packet_rescale_ts(pkt, pkt->time_base, ms->bsf_ctx->time_base_in); | |
325 | |||
326 | 10376 | ret = av_bsf_send_packet(ms->bsf_ctx, pkt); | |
327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10376 times.
|
10376 | if (ret < 0) { |
328 | ✗ | err_msg = "submitting a packet for bitstream filtering"; | |
329 | ✗ | goto fail; | |
330 | } | ||
331 | |||
332 |
2/2✓ Branch 0 taken 20018 times.
✓ Branch 1 taken 132 times.
|
20150 | while (!bsf_eof) { |
333 | 20018 | ret = av_bsf_receive_packet(ms->bsf_ctx, ms->bsf_pkt); | |
334 |
2/2✓ Branch 0 taken 10243 times.
✓ Branch 1 taken 9775 times.
|
20018 | if (ret == AVERROR(EAGAIN)) |
335 | 10243 | return 0; | |
336 |
2/2✓ Branch 0 taken 132 times.
✓ Branch 1 taken 9643 times.
|
9775 | else if (ret == AVERROR_EOF) |
337 | 132 | bsf_eof = 1; | |
338 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9641 times.
|
9643 | 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 9641 times.
✓ Branch 1 taken 132 times.
|
9773 | if (!bsf_eof) |
348 | 9641 | ms->bsf_pkt->time_base = ms->bsf_ctx->time_base_out; | |
349 | |||
350 |
2/2✓ Branch 0 taken 9641 times.
✓ Branch 1 taken 132 times.
|
9773 | ret = sync_queue_process(mux, ms, bsf_eof ? NULL : ms->bsf_pkt, stream_eof); |
351 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9772 times.
|
9773 | if (ret < 0) |
352 | 1 | goto mux_fail; | |
353 | } | ||
354 | 132 | *stream_eof = 1; | |
355 | } else { | ||
356 | 494934 | ret = sync_queue_process(mux, ms, pkt, stream_eof); | |
357 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 494901 times.
|
494934 | if (ret < 0) |
358 | 33 | goto mux_fail; | |
359 | } | ||
360 | |||
361 |
2/2✓ Branch 0 taken 176 times.
✓ Branch 1 taken 494857 times.
|
495033 | return *stream_eof ? AVERROR_EOF : 0; |
362 | |||
363 | 34 | mux_fail: | |
364 | 34 | err_msg = "submitting a packet to the muxer"; | |
365 | |||
366 | 34 | fail: | |
367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (ret != AVERROR_EOF) |
368 | ✗ | av_log(ost, AV_LOG_ERROR, "Error %s: %s\n", err_msg, av_err2str(ret)); | |
369 | 34 | return ret; | |
370 | } | ||
371 | |||
372 | 7916 | static void thread_set_name(Muxer *mux) | |
373 | { | ||
374 | char name[16]; | ||
375 | 7916 | snprintf(name, sizeof(name), "mux%d:%s", | |
376 | 7916 | mux->of.index, mux->fc->oformat->name); | |
377 | 7916 | ff_thread_setname(name); | |
378 | 7916 | } | |
379 | |||
380 | 7916 | static void mux_thread_uninit(MuxThreadContext *mt) | |
381 | { | ||
382 | 7916 | av_packet_free(&mt->pkt); | |
383 | 7916 | av_packet_free(&mt->fix_sub_duration_pkt); | |
384 | |||
385 | 7916 | memset(mt, 0, sizeof(*mt)); | |
386 | 7916 | } | |
387 | |||
388 | 7916 | static int mux_thread_init(MuxThreadContext *mt) | |
389 | { | ||
390 | 7916 | memset(mt, 0, sizeof(*mt)); | |
391 | |||
392 | 7916 | mt->pkt = av_packet_alloc(); | |
393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | if (!mt->pkt) |
394 | ✗ | goto fail; | |
395 | |||
396 | 7916 | mt->fix_sub_duration_pkt = av_packet_alloc(); | |
397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | if (!mt->fix_sub_duration_pkt) |
398 | ✗ | goto fail; | |
399 | |||
400 | 7916 | return 0; | |
401 | |||
402 | ✗ | fail: | |
403 | ✗ | mux_thread_uninit(mt); | |
404 | ✗ | return AVERROR(ENOMEM); | |
405 | } | ||
406 | |||
407 | 7916 | int muxer_thread(void *arg) | |
408 | { | ||
409 | 7916 | Muxer *mux = arg; | |
410 | 7916 | OutputFile *of = &mux->of; | |
411 | |||
412 | MuxThreadContext mt; | ||
413 | |||
414 | 7916 | int ret = 0; | |
415 | |||
416 | 7916 | ret = mux_thread_init(&mt); | |
417 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | if (ret < 0) |
418 | ✗ | goto finish; | |
419 | |||
420 | 7916 | thread_set_name(mux); | |
421 | |||
422 | 505546 | while (1) { | |
423 | OutputStream *ost; | ||
424 | 513462 | int stream_idx, stream_eof = 0; | |
425 | |||
426 | 513462 | ret = sch_mux_receive(mux->sch, of->index, mt.pkt); | |
427 | 513462 | stream_idx = mt.pkt->stream_index; | |
428 |
2/2✓ Branch 0 taken 7905 times.
✓ Branch 1 taken 505557 times.
|
513462 | if (stream_idx < 0) { |
429 | 7905 | av_log(mux, AV_LOG_VERBOSE, "All streams finished\n"); | |
430 | 7905 | ret = 0; | |
431 | 7916 | break; | |
432 | } | ||
433 | |||
434 | 505557 | ost = of->streams[mux->sch_stream_idx[stream_idx]]; | |
435 | 505557 | mt.pkt->stream_index = ost->index; | |
436 | 505557 | mt.pkt->flags &= ~AV_PKT_FLAG_TRUSTED; | |
437 | |||
438 |
2/2✓ Branch 0 taken 497278 times.
✓ Branch 1 taken 8279 times.
|
505557 | ret = mux_packet_filter(mux, &mt, ost, ret < 0 ? NULL : mt.pkt, &stream_eof); |
439 | 505557 | av_packet_unref(mt.pkt); | |
440 |
2/2✓ Branch 0 taken 210 times.
✓ Branch 1 taken 505347 times.
|
505557 | if (ret == AVERROR_EOF) { |
441 |
2/2✓ Branch 0 taken 199 times.
✓ Branch 1 taken 11 times.
|
210 | if (stream_eof) { |
442 | 199 | sch_mux_receive_finish(mux->sch, of->index, stream_idx); | |
443 | } else { | ||
444 | 11 | av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n"); | |
445 | 11 | ret = 0; | |
446 | 11 | break; | |
447 | } | ||
448 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505347 times.
|
505347 | } else if (ret < 0) { |
449 | ✗ | av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n"); | |
450 | ✗ | break; | |
451 | } | ||
452 | } | ||
453 | |||
454 | 7916 | finish: | |
455 | 7916 | mux_thread_uninit(&mt); | |
456 | |||
457 | 7916 | return ret; | |
458 | } | ||
459 | |||
460 | 67431 | static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt) | |
461 | { | ||
462 | 67431 | MuxStream *ms = ms_from_ost(ost); | |
463 |
1/2✓ Branch 0 taken 67431 times.
✗ Branch 1 not taken.
|
67431 | FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL; |
464 |
1/2✓ Branch 0 taken 67431 times.
✗ Branch 1 not taken.
|
67431 | int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE; |
465 |
2/2✓ Branch 0 taken 1073 times.
✓ Branch 1 taken 66358 times.
|
67431 | 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 66090 times.
|
67431 | 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 887 times.
✓ Branch 1 taken 66499 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 823 times.
|
67386 | 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 823 times.
✓ Branch 1 taken 66499 times.
|
67322 | if (!ms->streamcopy_started) { |
477 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 823 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
823 | 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 636 times.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 4 times.
|
823 | if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) |
484 | 183 | return AVERROR(EAGAIN); | |
485 | } | ||
486 | |||
487 | 67139 | ts_offset = av_rescale_q(start_time, AV_TIME_BASE_Q, pkt->time_base); | |
488 | |||
489 |
2/2✓ Branch 0 taken 57700 times.
✓ Branch 1 taken 9439 times.
|
67139 | if (pkt->pts != AV_NOPTS_VALUE) |
490 | 57700 | pkt->pts -= ts_offset; | |
491 | |||
492 |
2/2✓ Branch 0 taken 9205 times.
✓ Branch 1 taken 57934 times.
|
67139 | if (pkt->dts == AV_NOPTS_VALUE) { |
493 | 9205 | pkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, pkt->time_base); | |
494 |
2/2✓ Branch 0 taken 47438 times.
✓ Branch 1 taken 10496 times.
|
57934 | } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
495 | 47438 | pkt->pts = pkt->dts - ts_offset; | |
496 | } | ||
497 | |||
498 | 67139 | pkt->dts -= ts_offset; | |
499 | |||
500 | 67139 | ms->streamcopy_started = 1; | |
501 | |||
502 | 67139 | 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 | 7916 | int mux_check_init(void *arg) | |
556 | { | ||
557 | 7916 | Muxer *mux = arg; | |
558 | 7916 | OutputFile *of = &mux->of; | |
559 | 7916 | AVFormatContext *fc = mux->fc; | |
560 | int ret; | ||
561 | |||
562 | 7916 | ret = avformat_write_header(fc, &mux->opts); | |
563 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | 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 | 7916 | mux->header_written = 1; | |
570 | |||
571 | 7916 | av_dump_format(fc, of->index, fc->url, 1); | |
572 | 7916 | atomic_fetch_add(&nb_output_dumped, 1); | |
573 | |||
574 | 7916 | return 0; | |
575 | } | ||
576 | |||
577 | 8357 | static int bsf_init(MuxStream *ms) | |
578 | { | ||
579 | 8357 | OutputStream *ost = &ms->ost; | |
580 | 8357 | AVBSFContext *ctx = ms->bsf_ctx; | |
581 | int ret; | ||
582 | |||
583 |
2/2✓ Branch 0 taken 8224 times.
✓ Branch 1 taken 133 times.
|
8357 | if (!ctx) |
584 | 8224 | return avcodec_parameters_copy(ost->st->codecpar, ms->par_in); | |
585 | |||
586 | 133 | ret = avcodec_parameters_copy(ctx->par_in, ms->par_in); | |
587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
|
133 | if (ret < 0) |
588 | ✗ | return ret; | |
589 | |||
590 | 133 | ctx->time_base_in = ost->st->time_base; | |
591 | |||
592 | 133 | ret = av_bsf_init(ctx); | |
593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
|
133 | 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 | 133 | ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); | |
600 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
|
133 | if (ret < 0) |
601 | ✗ | return ret; | |
602 | 133 | ost->st->time_base = ctx->time_base_out; | |
603 | |||
604 | 133 | ms->bsf_pkt = av_packet_alloc(); | |
605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
|
133 | if (!ms->bsf_pkt) |
606 | ✗ | return AVERROR(ENOMEM); | |
607 | |||
608 | 133 | return 0; | |
609 | } | ||
610 | |||
611 | 8357 | int of_stream_init(OutputFile *of, OutputStream *ost, | |
612 | const AVCodecContext *enc_ctx) | ||
613 | { | ||
614 | 8357 | Muxer *mux = mux_from_of(of); | |
615 | 8357 | MuxStream *ms = ms_from_ost(ost); | |
616 | int ret; | ||
617 | |||
618 |
2/2✓ Branch 0 taken 7696 times.
✓ Branch 1 taken 661 times.
|
8357 | if (enc_ctx) { |
619 | // use upstream time base unless it has been overridden previously | ||
620 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7694 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
7696 | if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) |
621 | 7694 | ost->st->time_base = av_add_q(enc_ctx->time_base, (AVRational){0, 1}); | |
622 | |||
623 | 7696 | ost->st->avg_frame_rate = enc_ctx->framerate; | |
624 | 7696 | ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio; | |
625 | |||
626 | 7696 | ret = avcodec_parameters_from_context(ms->par_in, enc_ctx); | |
627 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7696 times.
|
7696 | if (ret < 0) { |
628 | ✗ | av_log(ost, AV_LOG_FATAL, | |
629 | "Error initializing the output stream codec parameters.\n"); | ||
630 | ✗ | return ret; | |
631 | } | ||
632 | } | ||
633 | |||
634 | /* initialize bitstream filters for the output stream | ||
635 | * needs to be done here, because the codec id for streamcopy is not | ||
636 | * known until now */ | ||
637 | 8357 | ret = bsf_init(ms); | |
638 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8357 times.
|
8357 | if (ret < 0) |
639 | ✗ | return ret; | |
640 | |||
641 |
2/2✓ Branch 0 taken 5798 times.
✓ Branch 1 taken 2559 times.
|
8357 | if (ms->stream_duration) { |
642 | 5798 | ost->st->duration = av_rescale_q(ms->stream_duration, ms->stream_duration_tb, | |
643 | 5798 | ost->st->time_base); | |
644 | } | ||
645 | |||
646 |
2/2✓ Branch 0 taken 8356 times.
✓ Branch 1 taken 1 times.
|
8357 | if (ms->sch_idx >= 0) |
647 | 8356 | return sch_mux_stream_ready(mux->sch, of->index, ms->sch_idx); | |
648 | |||
649 | 1 | return 0; | |
650 | } | ||
651 | |||
652 | 7916 | static int check_written(OutputFile *of) | |
653 | { | ||
654 | 7916 | int64_t total_packets_written = 0; | |
655 | 7916 | int pass1_used = 1; | |
656 | 7916 | int ret = 0; | |
657 | |||
658 |
2/2✓ Branch 0 taken 8357 times.
✓ Branch 1 taken 7916 times.
|
16273 | for (int i = 0; i < of->nb_streams; i++) { |
659 | 8357 | OutputStream *ost = of->streams[i]; | |
660 | 8357 | uint64_t packets_written = atomic_load(&ost->packets_written); | |
661 | |||
662 | 8357 | total_packets_written += packets_written; | |
663 | |||
664 |
2/2✓ Branch 0 taken 7696 times.
✓ Branch 1 taken 661 times.
|
8357 | if (ost->enc && |
665 |
2/2✓ Branch 0 taken 7688 times.
✓ Branch 1 taken 8 times.
|
7696 | (ost->enc->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) |
666 | != AV_CODEC_FLAG_PASS1) | ||
667 | 7688 | pass1_used = 0; | |
668 | |||
669 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 8309 times.
|
8357 | if (!packets_written && |
670 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { |
671 | ✗ | av_log(ost, AV_LOG_FATAL, "Empty output stream\n"); | |
672 | ✗ | ret = err_merge(ret, AVERROR(EINVAL)); | |
673 | } | ||
674 | } | ||
675 | |||
676 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 7901 times.
|
7916 | if (!total_packets_written) { |
677 | 15 | int level = AV_LOG_WARNING; | |
678 | |||
679 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT) { |
680 | ✗ | ret = err_merge(ret, AVERROR(EINVAL)); | |
681 | ✗ | level = AV_LOG_FATAL; | |
682 | } | ||
683 | |||
684 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
|
15 | av_log(of, level, "Output file is empty, nothing was encoded%s\n", |
685 | pass1_used ? "" : "(check -ss / -t / -frames parameters if used)"); | ||
686 | } | ||
687 | |||
688 | 7916 | return ret; | |
689 | } | ||
690 | |||
691 | 7916 | static void mux_final_stats(Muxer *mux) | |
692 | { | ||
693 | 7916 | OutputFile *of = &mux->of; | |
694 | 7916 | uint64_t total_packets = 0, total_size = 0; | |
695 | 7916 | uint64_t video_size = 0, audio_size = 0, subtitle_size = 0, | |
696 | 7916 | extra_size = 0, other_size = 0; | |
697 | |||
698 | 7916 | uint8_t overhead[16] = "unknown"; | |
699 | 7916 | int64_t file_size = of_filesize(of); | |
700 | |||
701 | 7916 | av_log(of, AV_LOG_VERBOSE, "Output file #%d (%s):\n", | |
702 | of->index, of->url); | ||
703 | |||
704 |
2/2✓ Branch 0 taken 8357 times.
✓ Branch 1 taken 7916 times.
|
16273 | for (int j = 0; j < of->nb_streams; j++) { |
705 | 8357 | OutputStream *ost = of->streams[j]; | |
706 | 8357 | MuxStream *ms = ms_from_ost(ost); | |
707 | 8357 | const AVCodecParameters *par = ost->st->codecpar; | |
708 | 8357 | const enum AVMediaType type = par->codec_type; | |
709 | 8357 | const uint64_t s = ms->data_size_mux; | |
710 | |||
711 |
4/4✓ Branch 0 taken 6681 times.
✓ Branch 1 taken 1594 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 11 times.
|
8357 | switch (type) { |
712 | 6681 | case AVMEDIA_TYPE_VIDEO: video_size += s; break; | |
713 | 1594 | case AVMEDIA_TYPE_AUDIO: audio_size += s; break; | |
714 | 71 | case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break; | |
715 | 11 | default: other_size += s; break; | |
716 | } | ||
717 | |||
718 | 8357 | extra_size += par->extradata_size; | |
719 | 8357 | total_size += s; | |
720 | 8357 | total_packets += atomic_load(&ost->packets_written); | |
721 | |||
722 | 8357 | av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", | |
723 | of->index, j, av_get_media_type_string(type)); | ||
724 |
2/2✓ Branch 0 taken 7696 times.
✓ Branch 1 taken 661 times.
|
8357 | if (ost->enc) { |
725 | 7696 | av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", | |
726 | 7696 | ost->enc->frames_encoded); | |
727 |
2/2✓ Branch 0 taken 1320 times.
✓ Branch 1 taken 6376 times.
|
7696 | if (type == AVMEDIA_TYPE_AUDIO) |
728 | 1320 | av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->enc->samples_encoded); | |
729 | 7696 | av_log(of, AV_LOG_VERBOSE, "; "); | |
730 | } | ||
731 | |||
732 | 8357 | av_log(of, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", | |
733 | 8357 | atomic_load(&ost->packets_written), s); | |
734 | |||
735 | 8357 | av_log(of, AV_LOG_VERBOSE, "\n"); | |
736 | } | ||
737 | |||
738 | 7916 | av_log(of, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", | |
739 | total_packets, total_size); | ||
740 | |||
741 |
6/6✓ Branch 0 taken 7901 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 7808 times.
✓ Branch 3 taken 93 times.
✓ Branch 4 taken 5760 times.
✓ Branch 5 taken 2048 times.
|
7916 | if (total_size && file_size > 0 && file_size >= total_size) { |
742 | 5760 | snprintf(overhead, sizeof(overhead), "%f%%", | |
743 | 5760 | 100.0 * (file_size - total_size) / total_size); | |
744 | } | ||
745 | |||
746 | 7916 | av_log(of, AV_LOG_INFO, | |
747 | "video:%1.0fKiB audio:%1.0fKiB subtitle:%1.0fKiB other streams:%1.0fKiB " | ||
748 | "global headers:%1.0fKiB muxing overhead: %s\n", | ||
749 | video_size / 1024.0, | ||
750 | audio_size / 1024.0, | ||
751 | subtitle_size / 1024.0, | ||
752 | other_size / 1024.0, | ||
753 | extra_size / 1024.0, | ||
754 | overhead); | ||
755 | 7916 | } | |
756 | |||
757 | 7916 | int of_write_trailer(OutputFile *of) | |
758 | { | ||
759 | 7916 | Muxer *mux = mux_from_of(of); | |
760 | 7916 | AVFormatContext *fc = mux->fc; | |
761 | 7916 | int ret, mux_result = 0; | |
762 | |||
763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | if (!mux->header_written) { |
764 | ✗ | av_log(mux, AV_LOG_ERROR, | |
765 | "Nothing was written into output file, because " | ||
766 | "at least one of its streams received no packets.\n"); | ||
767 | ✗ | return AVERROR(EINVAL); | |
768 | } | ||
769 | |||
770 | 7916 | ret = av_write_trailer(fc); | |
771 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | if (ret < 0) { |
772 | ✗ | av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret)); | |
773 | ✗ | mux_result = err_merge(mux_result, ret); | |
774 | } | ||
775 | |||
776 | 7916 | mux->last_filesize = filesize(fc->pb); | |
777 | |||
778 |
2/2✓ Branch 0 taken 7823 times.
✓ Branch 1 taken 93 times.
|
7916 | if (!(fc->oformat->flags & AVFMT_NOFILE)) { |
779 | 7823 | ret = avio_closep(&fc->pb); | |
780 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7823 times.
|
7823 | if (ret < 0) { |
781 | ✗ | av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret)); | |
782 | ✗ | mux_result = err_merge(mux_result, ret); | |
783 | } | ||
784 | } | ||
785 | |||
786 | 7916 | mux_final_stats(mux); | |
787 | |||
788 | // check whether anything was actually written | ||
789 | 7916 | ret = check_written(of); | |
790 | 7916 | mux_result = err_merge(mux_result, ret); | |
791 | |||
792 | 7916 | return mux_result; | |
793 | } | ||
794 | |||
795 | 25071 | static void enc_stats_uninit(EncStats *es) | |
796 | { | ||
797 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25071 times.
|
25071 | for (int i = 0; i < es->nb_components; i++) |
798 | ✗ | av_freep(&es->components[i].str); | |
799 | 25071 | av_freep(&es->components); | |
800 | |||
801 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25071 times.
|
25071 | if (es->lock_initialized) |
802 | ✗ | pthread_mutex_destroy(&es->lock); | |
803 | 25071 | es->lock_initialized = 0; | |
804 | 25071 | } | |
805 | |||
806 | 8357 | static void ost_free(OutputStream **post) | |
807 | { | ||
808 | 8357 | OutputStream *ost = *post; | |
809 | MuxStream *ms; | ||
810 | |||
811 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8357 times.
|
8357 | if (!ost) |
812 | ✗ | return; | |
813 | 8357 | ms = ms_from_ost(ost); | |
814 | |||
815 | 8357 | enc_free(&ost->enc); | |
816 | 8357 | fg_free(&ost->fg_simple); | |
817 | |||
818 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8349 times.
|
8357 | if (ost->logfile) { |
819 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if (fclose(ost->logfile)) |
820 | ✗ | av_log(ms, AV_LOG_ERROR, | |
821 | "Error closing logfile, loss of information possible: %s\n", | ||
822 | ✗ | av_err2str(AVERROR(errno))); | |
823 | 8 | ost->logfile = NULL; | |
824 | } | ||
825 | |||
826 | 8357 | avcodec_parameters_free(&ms->par_in); | |
827 | |||
828 | 8357 | av_bsf_free(&ms->bsf_ctx); | |
829 | 8357 | av_packet_free(&ms->bsf_pkt); | |
830 | |||
831 | 8357 | av_packet_free(&ms->pkt); | |
832 | |||
833 | 8357 | av_freep(&ost->kf.pts); | |
834 | 8357 | av_expr_free(ost->kf.pexpr); | |
835 | |||
836 | 8357 | av_freep(&ost->logfile_prefix); | |
837 | |||
838 | 8357 | av_freep(&ost->attachment_filename); | |
839 | |||
840 | 8357 | enc_stats_uninit(&ost->enc_stats_pre); | |
841 | 8357 | enc_stats_uninit(&ost->enc_stats_post); | |
842 | 8357 | enc_stats_uninit(&ms->stats); | |
843 | |||
844 | 8357 | av_freep(post); | |
845 | } | ||
846 | |||
847 | 7916 | static void fc_close(AVFormatContext **pfc) | |
848 | { | ||
849 | 7916 | AVFormatContext *fc = *pfc; | |
850 | |||
851 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | if (!fc) |
852 | ✗ | return; | |
853 | |||
854 |
2/2✓ Branch 0 taken 7823 times.
✓ Branch 1 taken 93 times.
|
7916 | if (!(fc->oformat->flags & AVFMT_NOFILE)) |
855 | 7823 | avio_closep(&fc->pb); | |
856 | 7916 | avformat_free_context(fc); | |
857 | |||
858 | 7916 | *pfc = NULL; | |
859 | } | ||
860 | |||
861 | 7916 | void of_free(OutputFile **pof) | |
862 | { | ||
863 | 7916 | OutputFile *of = *pof; | |
864 | Muxer *mux; | ||
865 | |||
866 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7916 times.
|
7916 | if (!of) |
867 | ✗ | return; | |
868 | 7916 | mux = mux_from_of(of); | |
869 | |||
870 | 7916 | sq_free(&mux->sq_mux); | |
871 | |||
872 |
2/2✓ Branch 0 taken 8357 times.
✓ Branch 1 taken 7916 times.
|
16273 | for (int i = 0; i < of->nb_streams; i++) |
873 | 8357 | ost_free(&of->streams[i]); | |
874 | 7916 | av_freep(&of->streams); | |
875 | |||
876 | 7916 | av_freep(&mux->sch_stream_idx); | |
877 | |||
878 | 7916 | av_dict_free(&mux->opts); | |
879 | 7916 | av_dict_free(&mux->enc_opts_used); | |
880 | |||
881 | 7916 | av_packet_free(&mux->sq_pkt); | |
882 | |||
883 | 7916 | fc_close(&mux->fc); | |
884 | |||
885 | 7916 | av_freep(pof); | |
886 | } | ||
887 | |||
888 | 32209 | int64_t of_filesize(OutputFile *of) | |
889 | { | ||
890 | 32209 | Muxer *mux = mux_from_of(of); | |
891 | 32209 | return atomic_load(&mux->last_filesize); | |
892 | } | ||
893 |