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 "objpool.h" | ||
26 | #include "sync_queue.h" | ||
27 | #include "thread_queue.h" | ||
28 | |||
29 | #include "libavutil/fifo.h" | ||
30 | #include "libavutil/intreadwrite.h" | ||
31 | #include "libavutil/log.h" | ||
32 | #include "libavutil/mem.h" | ||
33 | #include "libavutil/timestamp.h" | ||
34 | #include "libavutil/thread.h" | ||
35 | |||
36 | #include "libavcodec/packet.h" | ||
37 | |||
38 | #include "libavformat/avformat.h" | ||
39 | #include "libavformat/avio.h" | ||
40 | |||
41 | int want_sdp = 1; | ||
42 | |||
43 | 988325 | static Muxer *mux_from_of(OutputFile *of) | |
44 | { | ||
45 | 988325 | return (Muxer*)of; | |
46 | } | ||
47 | |||
48 | 490437 | static int64_t filesize(AVIOContext *pb) | |
49 | { | ||
50 | 490437 | int64_t ret = -1; | |
51 | |||
52 |
2/2✓ Branch 0 taken 481389 times.
✓ Branch 1 taken 9048 times.
|
490437 | if (pb) { |
53 | 481389 | ret = avio_size(pb); | |
54 |
2/2✓ Branch 0 taken 101515 times.
✓ Branch 1 taken 379874 times.
|
481389 | if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too |
55 | 101515 | ret = avio_tell(pb); | |
56 | } | ||
57 | |||
58 | 490437 | return ret; | |
59 | } | ||
60 | |||
61 | 483871 | static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) | |
62 | { | ||
63 | 483871 | MuxStream *ms = ms_from_ost(ost); | |
64 | 483871 | AVFormatContext *s = mux->fc; | |
65 | int64_t fs; | ||
66 | uint64_t frame_num; | ||
67 | int ret; | ||
68 | |||
69 | 483871 | fs = filesize(s->pb); | |
70 | 483871 | atomic_store(&mux->last_filesize, fs); | |
71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483871 times.
|
483871 | if (fs >= mux->limit_filesize) { |
72 | ✗ | ret = AVERROR_EOF; | |
73 | ✗ | goto fail; | |
74 | } | ||
75 | |||
76 |
3/4✓ Branch 0 taken 117551 times.
✓ Branch 1 taken 366320 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 117551 times.
|
483871 | if (ost->type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP) |
77 | ✗ | pkt->pts = pkt->dts = AV_NOPTS_VALUE; | |
78 | |||
79 | 483871 | av_packet_rescale_ts(pkt, pkt->time_base, ost->st->time_base); | |
80 | 483871 | pkt->time_base = ost->st->time_base; | |
81 | |||
82 |
2/2✓ Branch 0 taken 230716 times.
✓ Branch 1 taken 253155 times.
|
483871 | if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { |
83 |
1/2✓ Branch 0 taken 230716 times.
✗ Branch 1 not taken.
|
230716 | if (pkt->dts != AV_NOPTS_VALUE && |
84 |
2/2✓ Branch 0 taken 228551 times.
✓ Branch 1 taken 2165 times.
|
230716 | pkt->pts != AV_NOPTS_VALUE && |
85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 228551 times.
|
228551 | pkt->dts > pkt->pts) { |
86 | ✗ | av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n", | |
87 | pkt->dts, pkt->pts, | ||
88 | ✗ | ost->file_index, ost->st->index); | |
89 | ✗ | pkt->pts = | |
90 | ✗ | pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1 | |
91 | ✗ | - FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1) | |
92 | ✗ | - FFMAX3(pkt->pts, pkt->dts, ms->last_mux_dts + 1); | |
93 | } | ||
94 |
6/6✓ Branch 0 taken 86728 times.
✓ Branch 1 taken 143988 times.
✓ Branch 2 taken 1215 times.
✓ Branch 3 taken 85513 times.
✓ Branch 4 taken 1200 times.
✓ Branch 5 taken 15 times.
|
230716 | if ((ost->type == AVMEDIA_TYPE_AUDIO || ost->type == AVMEDIA_TYPE_VIDEO || ost->type == AVMEDIA_TYPE_SUBTITLE) && |
95 |
1/2✓ Branch 0 taken 230701 times.
✗ Branch 1 not taken.
|
230701 | pkt->dts != AV_NOPTS_VALUE && |
96 |
2/2✓ Branch 0 taken 225315 times.
✓ Branch 1 taken 5386 times.
|
230701 | ms->last_mux_dts != AV_NOPTS_VALUE) { |
97 | 225315 | int64_t max = ms->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); | |
98 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 225285 times.
|
225315 | if (pkt->dts < max) { |
99 |
3/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
|
30 | int loglevel = max - pkt->dts > 2 || ost->type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; |
100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
30 | if (exit_on_error) |
101 | ✗ | loglevel = AV_LOG_ERROR; | |
102 | 30 | av_log(s, loglevel, "Non-monotonous DTS in output stream " | |
103 | "%d:%d; previous: %"PRId64", current: %"PRId64"; ", | ||
104 | 30 | ost->file_index, ost->st->index, ms->last_mux_dts, pkt->dts); | |
105 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
30 | if (exit_on_error) { |
106 | ✗ | ret = AVERROR(EINVAL); | |
107 | ✗ | goto fail; | |
108 | } | ||
109 | |||
110 | 30 | av_log(s, loglevel, "changing to %"PRId64". This may result " | |
111 | "in incorrect timestamps in the output file.\n", | ||
112 | max); | ||
113 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
30 | if (pkt->pts >= pkt->dts) |
114 | 30 | pkt->pts = FFMAX(pkt->pts, max); | |
115 | 30 | pkt->dts = max; | |
116 | } | ||
117 | } | ||
118 | } | ||
119 | 483871 | ms->last_mux_dts = pkt->dts; | |
120 | |||
121 | 483871 | ms->data_size_mux += pkt->size; | |
122 | 483871 | frame_num = atomic_fetch_add(&ost->packets_written, 1); | |
123 | |||
124 | 483871 | pkt->stream_index = ost->index; | |
125 | |||
126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483871 times.
|
483871 | if (debug_ts) { |
127 | ✗ | av_log(ost, AV_LOG_INFO, "muxer <- type:%s " | |
128 | "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n", | ||
129 | av_get_media_type_string(ost->type), | ||
130 | ✗ | av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), | |
131 | ✗ | av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base), | |
132 | ✗ | av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base), | |
133 | pkt->size | ||
134 | ); | ||
135 | } | ||
136 | |||
137 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483871 times.
|
483871 | if (ms->stats.io) |
138 | ✗ | enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num); | |
139 | |||
140 | 483871 | ret = av_interleaved_write_frame(s, pkt); | |
141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483871 times.
|
483871 | if (ret < 0) { |
142 | ✗ | av_log(ost, AV_LOG_ERROR, | |
143 | "Error submitting a packet to the muxer: %s\n", | ||
144 | ✗ | av_err2str(ret)); | |
145 | ✗ | goto fail; | |
146 | } | ||
147 | |||
148 | 483871 | return 0; | |
149 | ✗ | fail: | |
150 | ✗ | av_packet_unref(pkt); | |
151 | ✗ | return ret; | |
152 | } | ||
153 | |||
154 | 490757 | static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt, int *stream_eof) | |
155 | { | ||
156 | 490757 | OutputFile *of = &mux->of; | |
157 | |||
158 |
2/2✓ Branch 0 taken 838 times.
✓ Branch 1 taken 489919 times.
|
490757 | if (ost->sq_idx_mux >= 0) { |
159 | 838 | int ret = sq_send(mux->sq_mux, ost->sq_idx_mux, SQPKT(pkt)); | |
160 |
2/2✓ Branch 0 taken 802 times.
✓ Branch 1 taken 36 times.
|
838 | if (ret < 0) { |
161 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | if (ret == AVERROR_EOF) |
162 | 36 | *stream_eof = 1; | |
163 | |||
164 | 36 | return ret; | |
165 | } | ||
166 | |||
167 | 740 | while (1) { | |
168 | 1542 | ret = sq_receive(mux->sq_mux, -1, SQPKT(mux->sq_pkt)); | |
169 |
2/2✓ Branch 0 taken 802 times.
✓ Branch 1 taken 740 times.
|
1542 | if (ret < 0) |
170 |
3/4✓ Branch 0 taken 791 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 791 times.
|
802 | return (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) ? 0 : ret; |
171 | |||
172 | 740 | ret = write_packet(mux, of->streams[ret], | |
173 | mux->sq_pkt); | ||
174 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 740 times.
|
740 | if (ret < 0) |
175 | ✗ | return ret; | |
176 | } | ||
177 |
2/2✓ Branch 0 taken 483131 times.
✓ Branch 1 taken 6788 times.
|
489919 | } else if (pkt) |
178 | 483131 | return write_packet(mux, ost, pkt); | |
179 | |||
180 | 6788 | return 0; | |
181 | } | ||
182 | |||
183 | 6566 | static void thread_set_name(OutputFile *of) | |
184 | { | ||
185 | char name[16]; | ||
186 | 6566 | snprintf(name, sizeof(name), "mux%d:%s", of->index, of->format->name); | |
187 | 6566 | ff_thread_setname(name); | |
188 | 6566 | } | |
189 | |||
190 | 6566 | static void *muxer_thread(void *arg) | |
191 | { | ||
192 | 6566 | Muxer *mux = arg; | |
193 | 6566 | OutputFile *of = &mux->of; | |
194 | 6566 | AVPacket *pkt = NULL; | |
195 | 6566 | int ret = 0; | |
196 | |||
197 | 6566 | pkt = av_packet_alloc(); | |
198 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (!pkt) { |
199 | ✗ | ret = AVERROR(ENOMEM); | |
200 | ✗ | goto finish; | |
201 | } | ||
202 | |||
203 | 6566 | thread_set_name(of); | |
204 | |||
205 | 490757 | while (1) { | |
206 | OutputStream *ost; | ||
207 | 497323 | int stream_idx, stream_eof = 0; | |
208 | |||
209 | 497323 | ret = tq_receive(mux->tq, &stream_idx, pkt); | |
210 |
2/2✓ Branch 0 taken 6566 times.
✓ Branch 1 taken 490757 times.
|
497323 | if (stream_idx < 0) { |
211 | 6566 | av_log(mux, AV_LOG_VERBOSE, "All streams finished\n"); | |
212 | 6566 | ret = 0; | |
213 | 6566 | break; | |
214 | } | ||
215 | |||
216 | 490757 | ost = of->streams[stream_idx]; | |
217 |
2/2✓ Branch 0 taken 483955 times.
✓ Branch 1 taken 6802 times.
|
490757 | ret = sync_queue_process(mux, ost, ret < 0 ? NULL : pkt, &stream_eof); |
218 | 490757 | av_packet_unref(pkt); | |
219 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 490721 times.
|
490757 | if (ret == AVERROR_EOF) { |
220 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | if (stream_eof) { |
221 | 36 | tq_receive_finish(mux->tq, stream_idx); | |
222 | } else { | ||
223 | ✗ | av_log(mux, AV_LOG_VERBOSE, "Muxer returned EOF\n"); | |
224 | ✗ | ret = 0; | |
225 | ✗ | break; | |
226 | } | ||
227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 490721 times.
|
490721 | } else if (ret < 0) { |
228 | ✗ | av_log(mux, AV_LOG_ERROR, "Error muxing a packet\n"); | |
229 | ✗ | break; | |
230 | } | ||
231 | } | ||
232 | |||
233 | 6566 | finish: | |
234 | 6566 | av_packet_free(&pkt); | |
235 | |||
236 |
2/2✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 6566 times.
|
13388 | for (unsigned int i = 0; i < mux->fc->nb_streams; i++) |
237 | 6822 | tq_receive_finish(mux->tq, i); | |
238 | |||
239 | 6566 | av_log(mux, AV_LOG_VERBOSE, "Terminating muxer thread\n"); | |
240 | |||
241 | 6566 | return (void*)(intptr_t)ret; | |
242 | } | ||
243 | |||
244 | 495398 | static int thread_submit_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt) | |
245 | { | ||
246 | 495398 | int ret = 0; | |
247 | |||
248 |
4/4✓ Branch 0 taken 483977 times.
✓ Branch 1 taken 11421 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 483973 times.
|
495398 | if (!pkt || ost->finished & MUXER_FINISHED) |
249 | 11425 | goto finish; | |
250 | |||
251 | 483973 | ret = tq_send(mux->tq, ost->index, pkt); | |
252 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 483955 times.
|
483973 | if (ret < 0) |
253 | 18 | goto finish; | |
254 | |||
255 | 483955 | return 0; | |
256 | |||
257 | 11443 | finish: | |
258 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 11421 times.
|
11443 | if (pkt) |
259 | 22 | av_packet_unref(pkt); | |
260 | |||
261 | 11443 | ost->finished |= MUXER_FINISHED; | |
262 | 11443 | tq_send_finish(mux->tq, ost->index); | |
263 |
2/2✓ Branch 0 taken 11425 times.
✓ Branch 1 taken 18 times.
|
11443 | return ret == AVERROR_EOF ? 0 : ret; |
264 | } | ||
265 | |||
266 | 340 | static int queue_packet(OutputStream *ost, AVPacket *pkt) | |
267 | { | ||
268 | 340 | MuxStream *ms = ms_from_ost(ost); | |
269 | 340 | AVPacket *tmp_pkt = NULL; | |
270 | int ret; | ||
271 | |||
272 |
2/2✓ Branch 1 taken 18 times.
✓ Branch 2 taken 322 times.
|
340 | if (!av_fifo_can_write(ms->muxing_queue)) { |
273 | 18 | size_t cur_size = av_fifo_can_read(ms->muxing_queue); | |
274 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | size_t pkt_size = pkt ? pkt->size : 0; |
275 | 18 | unsigned int are_we_over_size = | |
276 | 18 | (ms->muxing_queue_data_size + pkt_size) > ms->muxing_queue_data_threshold; | |
277 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | size_t limit = are_we_over_size ? ms->max_muxing_queue_size : SIZE_MAX; |
278 | 18 | size_t new_size = FFMIN(2 * cur_size, limit); | |
279 | |||
280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (new_size <= cur_size) { |
281 | ✗ | av_log(ost, AV_LOG_ERROR, | |
282 | "Too many packets buffered for output stream %d:%d.\n", | ||
283 | ✗ | ost->file_index, ost->st->index); | |
284 | ✗ | return AVERROR(ENOSPC); | |
285 | } | ||
286 | 18 | ret = av_fifo_grow2(ms->muxing_queue, new_size - cur_size); | |
287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ret < 0) |
288 | ✗ | return ret; | |
289 | } | ||
290 | |||
291 |
2/2✓ Branch 0 taken 337 times.
✓ Branch 1 taken 3 times.
|
340 | if (pkt) { |
292 | 337 | ret = av_packet_make_refcounted(pkt); | |
293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 337 times.
|
337 | if (ret < 0) |
294 | ✗ | return ret; | |
295 | |||
296 | 337 | tmp_pkt = av_packet_alloc(); | |
297 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 337 times.
|
337 | if (!tmp_pkt) |
298 | ✗ | return AVERROR(ENOMEM); | |
299 | |||
300 | 337 | av_packet_move_ref(tmp_pkt, pkt); | |
301 | 337 | ms->muxing_queue_data_size += tmp_pkt->size; | |
302 | } | ||
303 | 340 | av_fifo_write(ms->muxing_queue, &tmp_pkt, 1); | |
304 | |||
305 | 340 | return 0; | |
306 | } | ||
307 | |||
308 | 495398 | static int submit_packet(Muxer *mux, AVPacket *pkt, OutputStream *ost) | |
309 | { | ||
310 | int ret; | ||
311 | |||
312 |
2/2✓ Branch 0 taken 495058 times.
✓ Branch 1 taken 340 times.
|
495398 | if (mux->tq) { |
313 | 495058 | return thread_submit_packet(mux, ost, pkt); | |
314 | } else { | ||
315 | /* the muxer is not initialized yet, buffer the packet */ | ||
316 | 340 | ret = queue_packet(ost, pkt); | |
317 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
|
340 | if (ret < 0) { |
318 | ✗ | if (pkt) | |
319 | ✗ | av_packet_unref(pkt); | |
320 | ✗ | return ret; | |
321 | } | ||
322 | } | ||
323 | |||
324 | 340 | return 0; | |
325 | } | ||
326 | |||
327 | 495409 | void of_output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof) | |
328 | { | ||
329 | 495409 | Muxer *mux = mux_from_of(of); | |
330 | 495409 | MuxStream *ms = ms_from_ost(ost); | |
331 | const char *err_msg; | ||
332 | 495409 | int ret = 0; | |
333 | |||
334 |
4/4✓ Branch 0 taken 483988 times.
✓ Branch 1 taken 11421 times.
✓ Branch 2 taken 483987 times.
✓ Branch 3 taken 1 times.
|
495409 | if (!eof && pkt->dts != AV_NOPTS_VALUE) |
335 | 483987 | ost->last_mux_dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q); | |
336 | |||
337 | /* apply the output bitstream filters */ | ||
338 |
2/2✓ Branch 0 taken 7554 times.
✓ Branch 1 taken 487855 times.
|
495409 | if (ms->bsf_ctx) { |
339 | 7554 | int bsf_eof = 0; | |
340 | |||
341 |
2/2✓ Branch 0 taken 7362 times.
✓ Branch 1 taken 192 times.
|
7554 | ret = av_bsf_send_packet(ms->bsf_ctx, eof ? NULL : pkt); |
342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7554 times.
|
7554 | if (ret < 0) { |
343 | ✗ | err_msg = "submitting a packet for bitstream filtering"; | |
344 | ✗ | goto fail; | |
345 | } | ||
346 | |||
347 |
2/2✓ Branch 0 taken 14905 times.
✓ Branch 1 taken 192 times.
|
15097 | while (!bsf_eof) { |
348 | 14905 | ret = av_bsf_receive_packet(ms->bsf_ctx, pkt); | |
349 |
2/2✓ Branch 0 taken 7360 times.
✓ Branch 1 taken 7545 times.
|
14905 | if (ret == AVERROR(EAGAIN)) |
350 | 7360 | return; | |
351 |
2/2✓ Branch 0 taken 192 times.
✓ Branch 1 taken 7353 times.
|
7545 | else if (ret == AVERROR_EOF) |
352 | 192 | bsf_eof = 1; | |
353 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7351 times.
|
7353 | else if (ret < 0) { |
354 | 2 | err_msg = "applying bitstream filters to a packet"; | |
355 | 2 | goto fail; | |
356 | } | ||
357 | |||
358 |
2/2✓ Branch 0 taken 7351 times.
✓ Branch 1 taken 192 times.
|
7543 | ret = submit_packet(mux, bsf_eof ? NULL : pkt, ost); |
359 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7543 times.
|
7543 | if (ret < 0) |
360 | ✗ | goto mux_fail; | |
361 | } | ||
362 | } else { | ||
363 |
2/2✓ Branch 0 taken 476626 times.
✓ Branch 1 taken 11229 times.
|
487855 | ret = submit_packet(mux, eof ? NULL : pkt, ost); |
364 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 487855 times.
|
487855 | if (ret < 0) |
365 | ✗ | goto mux_fail; | |
366 | } | ||
367 | |||
368 | 488047 | return; | |
369 | |||
370 | ✗ | mux_fail: | |
371 | ✗ | err_msg = "submitting a packet to the muxer"; | |
372 | |||
373 | 2 | fail: | |
374 | 2 | av_log(ost, AV_LOG_ERROR, "Error %s\n", err_msg); | |
375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (exit_on_error) |
376 | ✗ | exit_program(1); | |
377 | |||
378 | } | ||
379 | |||
380 | 68053 | void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts) | |
381 | { | ||
382 | 68053 | OutputFile *of = output_files[ost->file_index]; | |
383 | 68053 | MuxStream *ms = ms_from_ost(ost); | |
384 |
2/2✓ Branch 0 taken 1077 times.
✓ Branch 1 taken 66976 times.
|
68053 | int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; |
385 | 68053 | int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); | |
386 | 68053 | AVPacket *opkt = ost->pkt; | |
387 | |||
388 | 68053 | av_packet_unref(opkt); | |
389 | |||
390 |
2/2✓ Branch 0 taken 2727 times.
✓ Branch 1 taken 65326 times.
|
68053 | if (of->recording_time != INT64_MAX && |
391 |
2/2✓ Branch 0 taken 1536 times.
✓ Branch 1 taken 1191 times.
|
2727 | dts >= of->recording_time + start_time) |
392 | 1536 | pkt = NULL; | |
393 | |||
394 | // EOF: flush output bitstream filters. | ||
395 |
2/2✓ Branch 0 taken 2031 times.
✓ Branch 1 taken 66022 times.
|
68053 | if (!pkt) { |
396 | 2031 | of_output_packet(of, opkt, ost, 1); | |
397 | 2278 | return; | |
398 | } | ||
399 | |||
400 |
4/4✓ Branch 0 taken 722 times.
✓ Branch 1 taken 65300 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 658 times.
|
66022 | if (!ms->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && |
401 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | !ms->copy_initial_nonkeyframes) |
402 | 64 | return; | |
403 | |||
404 |
2/2✓ Branch 0 taken 658 times.
✓ Branch 1 taken 65300 times.
|
65958 | if (!ms->streamcopy_started) { |
405 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 658 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
658 | if (!ms->copy_prior_start && |
406 | ✗ | (pkt->pts == AV_NOPTS_VALUE ? | |
407 | ✗ | dts < ms->ts_copy_start : | |
408 | ✗ | pkt->pts < av_rescale_q(ms->ts_copy_start, AV_TIME_BASE_Q, pkt->time_base))) | |
409 | ✗ | return; | |
410 | |||
411 |
4/4✓ Branch 0 taken 187 times.
✓ Branch 1 taken 471 times.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 4 times.
|
658 | if (of->start_time != AV_NOPTS_VALUE && dts < of->start_time) |
412 | 183 | return; | |
413 | } | ||
414 | |||
415 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 65775 times.
|
65775 | if (av_packet_ref(opkt, pkt) < 0) |
416 | ✗ | exit_program(1); | |
417 | |||
418 | 65775 | opkt->time_base = ost->mux_timebase; | |
419 | |||
420 |
2/2✓ Branch 0 taken 58821 times.
✓ Branch 1 taken 6954 times.
|
65775 | if (pkt->pts != AV_NOPTS_VALUE) |
421 | 58821 | opkt->pts = av_rescale_q(pkt->pts, pkt->time_base, opkt->time_base) - ost_tb_start_time; | |
422 | |||
423 |
2/2✓ Branch 0 taken 6717 times.
✓ Branch 1 taken 59058 times.
|
65775 | if (pkt->dts == AV_NOPTS_VALUE) { |
424 | 6717 | opkt->dts = av_rescale_q(dts, AV_TIME_BASE_Q, opkt->time_base); | |
425 |
2/2✓ Branch 0 taken 50840 times.
✓ Branch 1 taken 8218 times.
|
59058 | } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
426 | 50840 | int duration = av_get_audio_frame_duration2(ost->par_in, pkt->size); | |
427 |
2/2✓ Branch 0 taken 15023 times.
✓ Branch 1 taken 35817 times.
|
50840 | if(!duration) |
428 | 15023 | duration = ost->par_in->frame_size; | |
429 | 101680 | opkt->dts = av_rescale_delta(pkt->time_base, pkt->dts, | |
430 | 50840 | (AVRational){1, ost->par_in->sample_rate}, duration, | |
431 | &ms->ts_rescale_delta_last, opkt->time_base); | ||
432 | /* dts will be set immediately afterwards to what pts is now */ | ||
433 | 50840 | opkt->pts = opkt->dts - ost_tb_start_time; | |
434 | } else | ||
435 | 8218 | opkt->dts = av_rescale_q(pkt->dts, pkt->time_base, opkt->time_base); | |
436 | 65775 | opkt->dts -= ost_tb_start_time; | |
437 | |||
438 | 65775 | opkt->duration = av_rescale_q(pkt->duration, pkt->time_base, opkt->time_base); | |
439 | |||
440 | { | ||
441 | 65775 | int ret = trigger_fix_sub_duration_heartbeat(ost, pkt); | |
442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65775 times.
|
65775 | if (ret < 0) { |
443 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
444 | "Subtitle heartbeat logic failed in %s! (%s)\n", | ||
445 | ✗ | __func__, av_err2str(ret)); | |
446 | ✗ | exit_program(1); | |
447 | } | ||
448 | } | ||
449 | |||
450 | 65775 | of_output_packet(of, opkt, ost, 0); | |
451 | |||
452 | 65775 | ms->streamcopy_started = 1; | |
453 | } | ||
454 | |||
455 | 13132 | static int thread_stop(Muxer *mux) | |
456 | { | ||
457 | void *ret; | ||
458 | |||
459 |
3/4✓ Branch 0 taken 13132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6566 times.
✓ Branch 3 taken 6566 times.
|
13132 | if (!mux || !mux->tq) |
460 | 6566 | return 0; | |
461 | |||
462 |
2/2✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 6566 times.
|
13388 | for (unsigned int i = 0; i < mux->fc->nb_streams; i++) |
463 | 6822 | tq_send_finish(mux->tq, i); | |
464 | |||
465 | 6566 | pthread_join(mux->thread, &ret); | |
466 | |||
467 | 6566 | tq_free(&mux->tq); | |
468 | |||
469 | 6566 | return (int)(intptr_t)ret; | |
470 | } | ||
471 | |||
472 | 967910 | static void pkt_move(void *dst, void *src) | |
473 | { | ||
474 | 967910 | av_packet_move_ref(dst, src); | |
475 | 967910 | } | |
476 | |||
477 | 6566 | static int thread_start(Muxer *mux) | |
478 | { | ||
479 | 6566 | AVFormatContext *fc = mux->fc; | |
480 | ObjPool *op; | ||
481 | int ret; | ||
482 | |||
483 | 6566 | op = objpool_alloc_packets(); | |
484 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (!op) |
485 | ✗ | return AVERROR(ENOMEM); | |
486 | |||
487 | 6566 | mux->tq = tq_alloc(fc->nb_streams, mux->thread_queue_size, op, pkt_move); | |
488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (!mux->tq) { |
489 | ✗ | objpool_free(&op); | |
490 | ✗ | return AVERROR(ENOMEM); | |
491 | } | ||
492 | |||
493 | 6566 | ret = pthread_create(&mux->thread, NULL, muxer_thread, (void*)mux); | |
494 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (ret) { |
495 | ✗ | tq_free(&mux->tq); | |
496 | ✗ | return AVERROR(ret); | |
497 | } | ||
498 | |||
499 | /* flush the muxing queues */ | ||
500 |
2/2✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 6566 times.
|
13388 | for (int i = 0; i < fc->nb_streams; i++) { |
501 | 6822 | OutputStream *ost = mux->of.streams[i]; | |
502 | 6822 | MuxStream *ms = ms_from_ost(ost); | |
503 | AVPacket *pkt; | ||
504 | |||
505 | /* try to improve muxing time_base (only possible if nothing has been written yet) */ | ||
506 |
2/2✓ Branch 1 taken 6724 times.
✓ Branch 2 taken 98 times.
|
6822 | if (!av_fifo_can_read(ms->muxing_queue)) |
507 | 6724 | ost->mux_timebase = ost->st->time_base; | |
508 | |||
509 |
2/2✓ Branch 1 taken 340 times.
✓ Branch 2 taken 6822 times.
|
7162 | while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) { |
510 | 340 | ret = thread_submit_packet(mux, ost, pkt); | |
511 |
2/2✓ Branch 0 taken 337 times.
✓ Branch 1 taken 3 times.
|
340 | if (pkt) { |
512 | 337 | ms->muxing_queue_data_size -= pkt->size; | |
513 | 337 | av_packet_free(&pkt); | |
514 | } | ||
515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
|
340 | if (ret < 0) |
516 | ✗ | return ret; | |
517 | } | ||
518 | } | ||
519 | |||
520 | 6566 | return 0; | |
521 | } | ||
522 | |||
523 | ✗ | static int print_sdp(void) | |
524 | { | ||
525 | char sdp[16384]; | ||
526 | int i; | ||
527 | int j, ret; | ||
528 | AVIOContext *sdp_pb; | ||
529 | AVFormatContext **avc; | ||
530 | |||
531 | ✗ | for (i = 0; i < nb_output_files; i++) { | |
532 | ✗ | if (!mux_from_of(output_files[i])->header_written) | |
533 | ✗ | return 0; | |
534 | } | ||
535 | |||
536 | ✗ | avc = av_malloc_array(nb_output_files, sizeof(*avc)); | |
537 | ✗ | if (!avc) | |
538 | ✗ | return AVERROR(ENOMEM); | |
539 | ✗ | for (i = 0, j = 0; i < nb_output_files; i++) { | |
540 | ✗ | if (!strcmp(output_files[i]->format->name, "rtp")) { | |
541 | ✗ | avc[j] = mux_from_of(output_files[i])->fc; | |
542 | ✗ | j++; | |
543 | } | ||
544 | } | ||
545 | |||
546 | ✗ | if (!j) { | |
547 | ✗ | av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n"); | |
548 | ✗ | ret = AVERROR(EINVAL); | |
549 | ✗ | goto fail; | |
550 | } | ||
551 | |||
552 | ✗ | ret = av_sdp_create(avc, j, sdp, sizeof(sdp)); | |
553 | ✗ | if (ret < 0) | |
554 | ✗ | goto fail; | |
555 | |||
556 | ✗ | if (!sdp_filename) { | |
557 | ✗ | printf("SDP:\n%s\n", sdp); | |
558 | ✗ | fflush(stdout); | |
559 | } else { | ||
560 | ✗ | ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL); | |
561 | ✗ | if (ret < 0) { | |
562 | ✗ | av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename); | |
563 | ✗ | goto fail; | |
564 | } | ||
565 | |||
566 | ✗ | avio_print(sdp_pb, sdp); | |
567 | ✗ | avio_closep(&sdp_pb); | |
568 | ✗ | av_freep(&sdp_filename); | |
569 | } | ||
570 | |||
571 | // SDP successfully written, allow muxer threads to start | ||
572 | ✗ | ret = 1; | |
573 | |||
574 | ✗ | fail: | |
575 | ✗ | av_freep(&avc); | |
576 | ✗ | return ret; | |
577 | } | ||
578 | |||
579 | 6822 | int mux_check_init(Muxer *mux) | |
580 | { | ||
581 | 6822 | OutputFile *of = &mux->of; | |
582 | 6822 | AVFormatContext *fc = mux->fc; | |
583 | int ret, i; | ||
584 | |||
585 |
2/2✓ Branch 0 taken 7395 times.
✓ Branch 1 taken 6566 times.
|
13961 | for (i = 0; i < fc->nb_streams; i++) { |
586 | 7395 | OutputStream *ost = of->streams[i]; | |
587 |
2/2✓ Branch 0 taken 256 times.
✓ Branch 1 taken 7139 times.
|
7395 | if (!ost->initialized) |
588 | 256 | return 0; | |
589 | } | ||
590 | |||
591 | 6566 | ret = avformat_write_header(fc, &mux->opts); | |
592 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (ret < 0) { |
593 | ✗ | av_log(mux, AV_LOG_ERROR, "Could not write header (incorrect codec " | |
594 | ✗ | "parameters ?): %s\n", av_err2str(ret)); | |
595 | ✗ | return ret; | |
596 | } | ||
597 | //assert_avoptions(of->opts); | ||
598 | 6566 | mux->header_written = 1; | |
599 | |||
600 | 6566 | av_dump_format(fc, of->index, fc->url, 1); | |
601 | 6566 | nb_output_dumped++; | |
602 | |||
603 |
2/4✓ Branch 0 taken 6566 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6566 times.
|
6566 | if (sdp_filename || want_sdp) { |
604 | ✗ | ret = print_sdp(); | |
605 | ✗ | if (ret < 0) { | |
606 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n"); | |
607 | ✗ | return ret; | |
608 | ✗ | } else if (ret == 1) { | |
609 | /* SDP is written only after all the muxers are ready, so now we | ||
610 | * start ALL the threads */ | ||
611 | ✗ | for (i = 0; i < nb_output_files; i++) { | |
612 | ✗ | ret = thread_start(mux_from_of(output_files[i])); | |
613 | ✗ | if (ret < 0) | |
614 | ✗ | return ret; | |
615 | } | ||
616 | } | ||
617 | } else { | ||
618 | 6566 | ret = thread_start(mux_from_of(of)); | |
619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (ret < 0) |
620 | ✗ | return ret; | |
621 | } | ||
622 | |||
623 | 6566 | return 0; | |
624 | } | ||
625 | |||
626 | 6822 | static int bsf_init(MuxStream *ms) | |
627 | { | ||
628 | 6822 | OutputStream *ost = &ms->ost; | |
629 | 6822 | AVBSFContext *ctx = ms->bsf_ctx; | |
630 | int ret; | ||
631 | |||
632 |
2/2✓ Branch 0 taken 6724 times.
✓ Branch 1 taken 98 times.
|
6822 | if (!ctx) |
633 | 6724 | return avcodec_parameters_copy(ost->st->codecpar, ost->par_in); | |
634 | |||
635 | 98 | ret = avcodec_parameters_copy(ctx->par_in, ost->par_in); | |
636 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
|
98 | if (ret < 0) |
637 | ✗ | return ret; | |
638 | |||
639 | 98 | ctx->time_base_in = ost->st->time_base; | |
640 | |||
641 | 98 | ret = av_bsf_init(ctx); | |
642 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
|
98 | if (ret < 0) { |
643 | ✗ | av_log(ms, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", | |
644 | ✗ | ctx->filter->name); | |
645 | ✗ | return ret; | |
646 | } | ||
647 | |||
648 | 98 | ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); | |
649 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
|
98 | if (ret < 0) |
650 | ✗ | return ret; | |
651 | 98 | ost->st->time_base = ctx->time_base_out; | |
652 | |||
653 | 98 | return 0; | |
654 | } | ||
655 | |||
656 | 6822 | int of_stream_init(OutputFile *of, OutputStream *ost) | |
657 | { | ||
658 | 6822 | Muxer *mux = mux_from_of(of); | |
659 | 6822 | MuxStream *ms = ms_from_ost(ost); | |
660 | int ret; | ||
661 | |||
662 | /* initialize bitstream filters for the output stream | ||
663 | * needs to be done here, because the codec id for streamcopy is not | ||
664 | * known until now */ | ||
665 | 6822 | ret = bsf_init(ms); | |
666 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6822 times.
|
6822 | if (ret < 0) |
667 | ✗ | return ret; | |
668 | |||
669 | 6822 | ost->initialized = 1; | |
670 | |||
671 | 6822 | return mux_check_init(mux); | |
672 | } | ||
673 | |||
674 | 6566 | static int check_written(OutputFile *of) | |
675 | { | ||
676 | 6566 | int64_t total_packets_written = 0; | |
677 | 6566 | int pass1_used = 1; | |
678 | 6566 | int ret = 0; | |
679 | |||
680 |
2/2✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 6566 times.
|
13388 | for (int i = 0; i < of->nb_streams; i++) { |
681 | 6822 | OutputStream *ost = of->streams[i]; | |
682 | 6822 | uint64_t packets_written = atomic_load(&ost->packets_written); | |
683 | |||
684 | 6822 | total_packets_written += packets_written; | |
685 | |||
686 |
2/2✓ Branch 0 taken 6326 times.
✓ Branch 1 taken 496 times.
|
6822 | if (ost->enc_ctx && |
687 |
2/2✓ Branch 0 taken 6322 times.
✓ Branch 1 taken 4 times.
|
6326 | (ost->enc_ctx->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) |
688 | != AV_CODEC_FLAG_PASS1) | ||
689 | 6322 | pass1_used = 0; | |
690 | |||
691 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 6785 times.
|
6822 | if (!packets_written && |
692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
|
37 | (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { |
693 | ✗ | av_log(ost, AV_LOG_FATAL, "Empty output stream\n"); | |
694 | ✗ | ret = err_merge(ret, AVERROR(EINVAL)); | |
695 | } | ||
696 | } | ||
697 | |||
698 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6554 times.
|
6566 | if (!total_packets_written) { |
699 | 12 | int level = AV_LOG_WARNING; | |
700 | |||
701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT) { |
702 | ✗ | ret = err_merge(ret, AVERROR(EINVAL)); | |
703 | ✗ | level = AV_LOG_FATAL; | |
704 | } | ||
705 | |||
706 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
|
12 | av_log(of, level, "Output file is empty, nothing was encoded%s\n", |
707 | pass1_used ? "" : "(check -ss / -t / -frames parameters if used)"); | ||
708 | } | ||
709 | |||
710 | 6566 | return ret; | |
711 | } | ||
712 | |||
713 | 6566 | static void mux_final_stats(Muxer *mux) | |
714 | { | ||
715 | 6566 | OutputFile *of = &mux->of; | |
716 | 6566 | uint64_t total_packets = 0, total_size = 0; | |
717 | 6566 | uint64_t video_size = 0, audio_size = 0, subtitle_size = 0, | |
718 | 6566 | extra_size = 0, other_size = 0; | |
719 | |||
720 | 6566 | uint8_t overhead[16] = "unknown"; | |
721 | 6566 | int64_t file_size = of_filesize(of); | |
722 | |||
723 | 6566 | av_log(of, AV_LOG_VERBOSE, "Output file #%d (%s):\n", | |
724 | of->index, of->url); | ||
725 | |||
726 |
2/2✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 6566 times.
|
13388 | for (int j = 0; j < of->nb_streams; j++) { |
727 | 6822 | OutputStream *ost = of->streams[j]; | |
728 | 6822 | MuxStream *ms = ms_from_ost(ost); | |
729 | 6822 | const AVCodecParameters *par = ost->st->codecpar; | |
730 | 6822 | const enum AVMediaType type = par->codec_type; | |
731 | 6822 | const uint64_t s = ms->data_size_mux; | |
732 | |||
733 |
4/4✓ Branch 0 taken 5344 times.
✓ Branch 1 taken 1397 times.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 13 times.
|
6822 | switch (type) { |
734 | 5344 | case AVMEDIA_TYPE_VIDEO: video_size += s; break; | |
735 | 1397 | case AVMEDIA_TYPE_AUDIO: audio_size += s; break; | |
736 | 68 | case AVMEDIA_TYPE_SUBTITLE: subtitle_size += s; break; | |
737 | 13 | default: other_size += s; break; | |
738 | } | ||
739 | |||
740 | 6822 | extra_size += par->extradata_size; | |
741 | 6822 | total_size += s; | |
742 | 6822 | total_packets += atomic_load(&ost->packets_written); | |
743 | |||
744 | 6822 | av_log(of, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", | |
745 | of->index, j, av_get_media_type_string(type)); | ||
746 |
2/2✓ Branch 0 taken 6326 times.
✓ Branch 1 taken 496 times.
|
6822 | if (ost->enc) { |
747 | 6326 | av_log(of, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", | |
748 | ost->frames_encoded); | ||
749 |
2/2✓ Branch 0 taken 1189 times.
✓ Branch 1 taken 5137 times.
|
6326 | if (type == AVMEDIA_TYPE_AUDIO) |
750 | 1189 | av_log(of, AV_LOG_VERBOSE, " (%"PRIu64" samples)", ost->samples_encoded); | |
751 | 6326 | av_log(of, AV_LOG_VERBOSE, "; "); | |
752 | } | ||
753 | |||
754 | 6822 | av_log(of, AV_LOG_VERBOSE, "%"PRIu64" packets muxed (%"PRIu64" bytes); ", | |
755 | 6822 | atomic_load(&ost->packets_written), s); | |
756 | |||
757 | 6822 | av_log(of, AV_LOG_VERBOSE, "\n"); | |
758 | } | ||
759 | |||
760 | 6566 | av_log(of, AV_LOG_VERBOSE, " Total: %"PRIu64" packets (%"PRIu64" bytes) muxed\n", | |
761 | total_packets, total_size); | ||
762 | |||
763 |
6/6✓ Branch 0 taken 6554 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 6467 times.
✓ Branch 3 taken 87 times.
✓ Branch 4 taken 4537 times.
✓ Branch 5 taken 1930 times.
|
6566 | if (total_size && file_size > 0 && file_size >= total_size) { |
764 | 4537 | snprintf(overhead, sizeof(overhead), "%f%%", | |
765 | 4537 | 100.0 * (file_size - total_size) / total_size); | |
766 | } | ||
767 | |||
768 | 6566 | av_log(of, AV_LOG_INFO, | |
769 | "video:%1.0fkB audio:%1.0fkB subtitle:%1.0fkB other streams:%1.0fkB " | ||
770 | "global headers:%1.0fkB muxing overhead: %s\n", | ||
771 | video_size / 1024.0, | ||
772 | audio_size / 1024.0, | ||
773 | subtitle_size / 1024.0, | ||
774 | other_size / 1024.0, | ||
775 | extra_size / 1024.0, | ||
776 | overhead); | ||
777 | 6566 | } | |
778 | |||
779 | 6566 | int of_write_trailer(OutputFile *of) | |
780 | { | ||
781 | 6566 | Muxer *mux = mux_from_of(of); | |
782 | 6566 | AVFormatContext *fc = mux->fc; | |
783 | 6566 | int ret, mux_result = 0; | |
784 | |||
785 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (!mux->tq) { |
786 | ✗ | av_log(mux, AV_LOG_ERROR, | |
787 | "Nothing was written into output file, because " | ||
788 | "at least one of its streams received no packets.\n"); | ||
789 | ✗ | return AVERROR(EINVAL); | |
790 | } | ||
791 | |||
792 | 6566 | mux_result = thread_stop(mux); | |
793 | |||
794 | 6566 | ret = av_write_trailer(fc); | |
795 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (ret < 0) { |
796 | ✗ | av_log(mux, AV_LOG_ERROR, "Error writing trailer: %s\n", av_err2str(ret)); | |
797 | ✗ | mux_result = err_merge(mux_result, ret); | |
798 | } | ||
799 | |||
800 | 6566 | mux->last_filesize = filesize(fc->pb); | |
801 | |||
802 |
2/2✓ Branch 0 taken 6479 times.
✓ Branch 1 taken 87 times.
|
6566 | if (!(of->format->flags & AVFMT_NOFILE)) { |
803 | 6479 | ret = avio_closep(&fc->pb); | |
804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6479 times.
|
6479 | if (ret < 0) { |
805 | ✗ | av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret)); | |
806 | ✗ | mux_result = err_merge(mux_result, ret); | |
807 | } | ||
808 | } | ||
809 | |||
810 | 6566 | mux_final_stats(mux); | |
811 | |||
812 | // check whether anything was actually written | ||
813 | 6566 | ret = check_written(of); | |
814 | 6566 | mux_result = err_merge(mux_result, ret); | |
815 | |||
816 | 6566 | return mux_result; | |
817 | } | ||
818 | |||
819 | 6822 | static void ost_free(OutputStream **post) | |
820 | { | ||
821 | 6822 | OutputStream *ost = *post; | |
822 | MuxStream *ms; | ||
823 | |||
824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6822 times.
|
6822 | if (!ost) |
825 | ✗ | return; | |
826 | 6822 | ms = ms_from_ost(ost); | |
827 | |||
828 | 6822 | enc_free(&ost->enc); | |
829 | |||
830 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6818 times.
|
6822 | if (ost->logfile) { |
831 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (fclose(ost->logfile)) |
832 | ✗ | av_log(ms, AV_LOG_ERROR, | |
833 | "Error closing logfile, loss of information possible: %s\n", | ||
834 | ✗ | av_err2str(AVERROR(errno))); | |
835 | 4 | ost->logfile = NULL; | |
836 | } | ||
837 | |||
838 |
1/2✓ Branch 0 taken 6822 times.
✗ Branch 1 not taken.
|
6822 | if (ms->muxing_queue) { |
839 | AVPacket *pkt; | ||
840 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6822 times.
|
6822 | while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) |
841 | ✗ | av_packet_free(&pkt); | |
842 | 6822 | av_fifo_freep2(&ms->muxing_queue); | |
843 | } | ||
844 | |||
845 | 6822 | avcodec_parameters_free(&ost->par_in); | |
846 | |||
847 | 6822 | av_bsf_free(&ms->bsf_ctx); | |
848 | |||
849 | 6822 | av_packet_free(&ost->pkt); | |
850 | 6822 | av_dict_free(&ost->encoder_opts); | |
851 | |||
852 | 6822 | av_freep(&ost->kf.pts); | |
853 | 6822 | av_expr_free(ost->kf.pexpr); | |
854 | |||
855 | 6822 | av_freep(&ost->logfile_prefix); | |
856 | 6822 | av_freep(&ost->apad); | |
857 | |||
858 | #if FFMPEG_OPT_MAP_CHANNEL | ||
859 | 6822 | av_freep(&ost->audio_channels_map); | |
860 | 6822 | ost->audio_channels_mapped = 0; | |
861 | #endif | ||
862 | |||
863 | 6822 | av_dict_free(&ost->sws_dict); | |
864 | 6822 | av_dict_free(&ost->swr_opts); | |
865 | |||
866 |
2/2✓ Branch 0 taken 6326 times.
✓ Branch 1 taken 496 times.
|
6822 | if (ost->enc_ctx) |
867 | 6326 | av_freep(&ost->enc_ctx->stats_in); | |
868 | 6822 | avcodec_free_context(&ost->enc_ctx); | |
869 | |||
870 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6822 times.
|
6822 | for (int i = 0; i < ost->enc_stats_pre.nb_components; i++) |
871 | ✗ | av_freep(&ost->enc_stats_pre.components[i].str); | |
872 | 6822 | av_freep(&ost->enc_stats_pre.components); | |
873 | |||
874 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6822 times.
|
6822 | for (int i = 0; i < ost->enc_stats_post.nb_components; i++) |
875 | ✗ | av_freep(&ost->enc_stats_post.components[i].str); | |
876 | 6822 | av_freep(&ost->enc_stats_post.components); | |
877 | |||
878 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6822 times.
|
6822 | for (int i = 0; i < ms->stats.nb_components; i++) |
879 | ✗ | av_freep(&ms->stats.components[i].str); | |
880 | 6822 | av_freep(&ms->stats.components); | |
881 | |||
882 | 6822 | av_freep(post); | |
883 | } | ||
884 | |||
885 | 6566 | static void fc_close(AVFormatContext **pfc) | |
886 | { | ||
887 | 6566 | AVFormatContext *fc = *pfc; | |
888 | |||
889 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (!fc) |
890 | ✗ | return; | |
891 | |||
892 |
2/2✓ Branch 0 taken 6479 times.
✓ Branch 1 taken 87 times.
|
6566 | if (!(fc->oformat->flags & AVFMT_NOFILE)) |
893 | 6479 | avio_closep(&fc->pb); | |
894 | 6566 | avformat_free_context(fc); | |
895 | |||
896 | 6566 | *pfc = NULL; | |
897 | } | ||
898 | |||
899 | 6566 | void of_close(OutputFile **pof) | |
900 | { | ||
901 | 6566 | OutputFile *of = *pof; | |
902 | Muxer *mux; | ||
903 | |||
904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6566 times.
|
6566 | if (!of) |
905 | ✗ | return; | |
906 | 6566 | mux = mux_from_of(of); | |
907 | |||
908 | 6566 | thread_stop(mux); | |
909 | |||
910 | 6566 | sq_free(&of->sq_encode); | |
911 | 6566 | sq_free(&mux->sq_mux); | |
912 | |||
913 |
2/2✓ Branch 0 taken 6822 times.
✓ Branch 1 taken 6566 times.
|
13388 | for (int i = 0; i < of->nb_streams; i++) |
914 | 6822 | ost_free(&of->streams[i]); | |
915 | 6566 | av_freep(&of->streams); | |
916 | |||
917 | 6566 | av_dict_free(&mux->opts); | |
918 | |||
919 | 6566 | av_packet_free(&mux->sq_pkt); | |
920 | |||
921 | 6566 | fc_close(&mux->fc); | |
922 | |||
923 | 6566 | av_freep(pof); | |
924 | } | ||
925 | |||
926 | 466396 | int64_t of_filesize(OutputFile *of) | |
927 | { | ||
928 | 466396 | Muxer *mux = mux_from_of(of); | |
929 | 466396 | return atomic_load(&mux->last_filesize); | |
930 | } | ||
931 |