2 * This file is part of FFmpeg.
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.
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.
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
19 #include <stdatomic.h>
24 #include "ffmpeg_mux.h"
25 #include "ffmpeg_utils.h"
26 #include "sync_queue.h"
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"
36 #include "libavcodec/packet.h"
38 #include "libavformat/avformat.h"
39 #include "libavformat/avio.h"
41 typedef struct MuxThreadContext
{
43 AVPacket
*fix_sub_duration_pkt
;
46 static Muxer
*mux_from_of(OutputFile
*of
)
51 static int64_t filesize(AVIOContext
*pb
)
57 if (ret
<= 0) // FIXME improve avio_size() so it works with non seekable output too
64 static void mux_log_debug_ts(OutputStream
*ost
, const AVPacket
*pkt
)
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",
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
;
87 for (unsigned i
= 0; i
< FF_ARRAY_ELEMS(fd
->wallclock
); i
= next
) {
88 int64_t val
= fd
->wallclock
[i
];
95 if (total
== INT64_MIN
) {
97 snprintf(latency
, sizeof(latency
), "total:%gms", total
/ 1e3
);
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
];
106 if (val_next
== INT64_MIN
)
108 diff
= val_next
- val
;
110 // print those stages that take at least 5% of total
111 if (100. * diff
> 5. * total
) {
112 av_strlcat(latency
, ", ", sizeof(latency
));
114 if (!strcmp(desc
[i
], desc
[next
]))
115 av_strlcat(latency
, desc
[i
], sizeof(latency
));
117 av_strlcatf(latency
, sizeof(latency
), "%s-%s:",
118 desc
[i
], desc
[next
]);
120 av_strlcatf(latency
, sizeof(latency
), " %gms/%d%%",
121 diff
/ 1e3
, (int)(100. * diff
/ total
));
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");
138 static int mux_fixup_ts(Muxer
*mux
, MuxStream
*ms
, AVPacket
*pkt
)
140 OutputStream
*ost
= &ms
->ost
;
142 #if FFMPEG_OPT_VSYNC_DROP
143 if (ost
->type
== AVMEDIA_TYPE_VIDEO
&& ms
->ts_drop
)
144 pkt
->pts
= pkt
->dts
= AV_NOPTS_VALUE
;
147 // rescale timestamps to the stream timebase
148 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 int duration
= av_get_audio_frame_duration2(ost
->st
->codecpar
, pkt
->size
);
154 duration
= ost
->st
->codecpar
->frame_size
;
156 pkt
->dts
= av_rescale_delta(pkt
->time_base
, pkt
->dts
,
157 (AVRational
){1, ost
->st
->codecpar
->sample_rate
}, duration
,
158 &ms
->ts_rescale_delta_last
, ost
->st
->time_base
);
161 pkt
->duration
= av_rescale_q(pkt
->duration
, pkt
->time_base
, ost
->st
->time_base
);
163 av_packet_rescale_ts(pkt
, pkt
->time_base
, ost
->st
->time_base
);
164 pkt
->time_base
= ost
->st
->time_base
;
166 if (!(mux
->fc
->oformat
->flags
& AVFMT_NOTIMESTAMPS
)) {
167 if (pkt
->dts
!= AV_NOPTS_VALUE
&&
168 pkt
->pts
!= AV_NOPTS_VALUE
&&
169 pkt
->dts
> pkt
->pts
) {
170 av_log(ost
, AV_LOG_WARNING
, "Invalid DTS: %"PRId64
" PTS: %"PRId64
", replacing by guess\n",
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);
177 if ((ost
->type
== AVMEDIA_TYPE_AUDIO
|| ost
->type
== AVMEDIA_TYPE_VIDEO
|| ost
->type
== AVMEDIA_TYPE_SUBTITLE
) &&
178 pkt
->dts
!= AV_NOPTS_VALUE
&&
179 ms
->last_mux_dts
!= AV_NOPTS_VALUE
) {
180 int64_t max
= ms
->last_mux_dts
+ !(mux
->fc
->oformat
->flags
& AVFMT_TS_NONSTRICT
);
181 if (pkt
->dts
< max
) {
182 int loglevel
= max
- pkt
->dts
> 2 || ost
->type
== AVMEDIA_TYPE_VIDEO
? AV_LOG_WARNING
: AV_LOG_DEBUG
;
184 loglevel
= AV_LOG_ERROR
;
185 av_log(ost
, loglevel
, "Non-monotonic DTS; "
186 "previous: %"PRId64
", current: %"PRId64
"; ",
187 ms
->last_mux_dts
, pkt
->dts
);
189 return AVERROR(EINVAL
);
192 av_log(ost
, loglevel
, "changing to %"PRId64
". This may result "
193 "in incorrect timestamps in the output file.\n",
195 if (pkt
->pts
>= pkt
->dts
)
196 pkt
->pts
= FFMAX(pkt
->pts
, max
);
201 ms
->last_mux_dts
= pkt
->dts
;
204 mux_log_debug_ts(ost
, pkt
);
209 static int write_packet(Muxer
*mux
, OutputStream
*ost
, AVPacket
*pkt
)
211 MuxStream
*ms
= ms_from_ost(ost
);
212 AVFormatContext
*s
= mux
->fc
;
217 fs
= filesize(s
->pb
);
218 atomic_store(&mux
->last_filesize
, fs
);
219 if (fs
>= mux
->limit_filesize
) {
224 ret
= mux_fixup_ts(mux
, ms
, pkt
);
228 ms
->data_size_mux
+= pkt
->size
;
229 frame_num
= atomic_fetch_add(&ost
->packets_written
, 1);
231 pkt
->stream_index
= ost
->index
;
234 enc_stats_write(ost
, &ms
->stats
, NULL
, pkt
, frame_num
);
236 ret
= av_interleaved_write_frame(s
, pkt
);
238 av_log(ost
, AV_LOG_ERROR
,
239 "Error submitting a packet to the muxer: %s\n",
246 av_packet_unref(pkt
);
250 static int sync_queue_process(Muxer
*mux
, MuxStream
*ms
, AVPacket
*pkt
, int *stream_eof
)
252 OutputFile
*of
= &mux
->of
;
254 if (ms
->sq_idx_mux
>= 0) {
255 int ret
= sq_send(mux
->sq_mux
, ms
->sq_idx_mux
, SQPKT(pkt
));
257 if (ret
== AVERROR_EOF
)
264 ret
= sq_receive(mux
->sq_mux
, -1, SQPKT(mux
->sq_pkt
));
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.
271 return ret
== AVERROR(EAGAIN
) ? 0 : ret
;
274 ret
= write_packet(mux
, of
->streams
[ret
],
280 return write_packet(mux
, &ms
->ost
, pkt
);
285 static int of_streamcopy(OutputFile
*of
, OutputStream
*ost
, AVPacket
*pkt
);
287 /* apply the output bitstream filters */
288 static int mux_packet_filter(Muxer
*mux
, MuxThreadContext
*mt
,
289 OutputStream
*ost
, AVPacket
*pkt
, int *stream_eof
)
291 MuxStream
*ms
= ms_from_ost(ost
);
295 if (pkt
&& !ost
->enc
) {
296 ret
= of_streamcopy(&mux
->of
, ost
, pkt
);
297 if (ret
== AVERROR(EAGAIN
))
299 else if (ret
== AVERROR_EOF
) {
300 av_packet_unref(pkt
);
307 // emit heartbeat for -fix_sub_duration;
308 // we are only interested in heartbeats on on random access points.
309 if (pkt
&& (pkt
->flags
& AV_PKT_FLAG_KEY
)) {
310 mt
->fix_sub_duration_pkt
->opaque
= (void*)(intptr_t)PKT_OPAQUE_FIX_SUB_DURATION
;
311 mt
->fix_sub_duration_pkt
->pts
= pkt
->pts
;
312 mt
->fix_sub_duration_pkt
->time_base
= pkt
->time_base
;
314 ret
= sch_mux_sub_heartbeat(mux
->sch
, mux
->sch_idx
, ms
->sch_idx
,
315 mt
->fix_sub_duration_pkt
);
324 av_packet_rescale_ts(pkt
, pkt
->time_base
, ms
->bsf_ctx
->time_base_in
);
326 ret
= av_bsf_send_packet(ms
->bsf_ctx
, pkt
);
328 err_msg
= "submitting a packet for bitstream filtering";
333 ret
= av_bsf_receive_packet(ms
->bsf_ctx
, ms
->bsf_pkt
);
334 if (ret
== AVERROR(EAGAIN
))
336 else if (ret
== AVERROR_EOF
)
339 av_log(ost
, AV_LOG_ERROR
,
340 "Error applying bitstream filters to a packet: %s",
348 ms
->bsf_pkt
->time_base
= ms
->bsf_ctx
->time_base_out
;
350 ret
= sync_queue_process(mux
, ms
, bsf_eof
? NULL
: ms
->bsf_pkt
, stream_eof
);
356 ret
= sync_queue_process(mux
, ms
, pkt
, stream_eof
);
361 return *stream_eof
? AVERROR_EOF
: 0;
364 err_msg
= "submitting a packet to the muxer";
367 if (ret
!= AVERROR_EOF
)
368 av_log(ost
, AV_LOG_ERROR
, "Error %s: %s\n", err_msg
, av_err2str(ret
));
372 static void thread_set_name(Muxer
*mux
)
375 snprintf(name
, sizeof(name
), "mux%d:%s",
376 mux
->of
.index
, mux
->fc
->oformat
->name
);
377 ff_thread_setname(name
);
380 static void mux_thread_uninit(MuxThreadContext
*mt
)
382 av_packet_free(&mt
->pkt
);
383 av_packet_free(&mt
->fix_sub_duration_pkt
);
385 memset(mt
, 0, sizeof(*mt
));
388 static int mux_thread_init(MuxThreadContext
*mt
)
390 memset(mt
, 0, sizeof(*mt
));
392 mt
->pkt
= av_packet_alloc();
396 mt
->fix_sub_duration_pkt
= av_packet_alloc();
397 if (!mt
->fix_sub_duration_pkt
)
403 mux_thread_uninit(mt
);
404 return AVERROR(ENOMEM
);
407 int muxer_thread(void *arg
)
410 OutputFile
*of
= &mux
->of
;
416 ret
= mux_thread_init(&mt
);
420 thread_set_name(mux
);
424 int stream_idx
, stream_eof
= 0;
426 ret
= sch_mux_receive(mux
->sch
, of
->index
, mt
.pkt
);
427 stream_idx
= mt
.pkt
->stream_index
;
428 if (stream_idx
< 0) {
429 av_log(mux
, AV_LOG_VERBOSE
, "All streams finished\n");
434 ost
= of
->streams
[mux
->sch_stream_idx
[stream_idx
]];
435 mt
.pkt
->stream_index
= ost
->index
;
436 mt
.pkt
->flags
&= ~AV_PKT_FLAG_TRUSTED
;
438 ret
= mux_packet_filter(mux
, &mt
, ost
, ret
< 0 ? NULL
: mt
.pkt
, &stream_eof
);
439 av_packet_unref(mt
.pkt
);
440 if (ret
== AVERROR_EOF
) {
442 sch_mux_receive_finish(mux
->sch
, of
->index
, stream_idx
);
444 av_log(mux
, AV_LOG_VERBOSE
, "Muxer returned EOF\n");
448 } else if (ret
< 0) {
449 av_log(mux
, AV_LOG_ERROR
, "Error muxing a packet\n");
455 mux_thread_uninit(&mt
);
460 static int of_streamcopy(OutputFile
*of
, OutputStream
*ost
, AVPacket
*pkt
)
462 MuxStream
*ms
= ms_from_ost(ost
);
463 FrameData
*fd
= pkt
->opaque_ref
? (FrameData
*)pkt
->opaque_ref
->data
: NULL
;
464 int64_t dts
= fd
? fd
->dts_est
: AV_NOPTS_VALUE
;
465 int64_t start_time
= (of
->start_time
== AV_NOPTS_VALUE
) ? 0 : of
->start_time
;
468 if (of
->recording_time
!= INT64_MAX
&&
469 dts
>= of
->recording_time
+ start_time
)
472 if (!ms
->streamcopy_started
&& !(pkt
->flags
& AV_PKT_FLAG_KEY
) &&
473 !ms
->copy_initial_nonkeyframes
)
474 return AVERROR(EAGAIN
);
476 if (!ms
->streamcopy_started
) {
477 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
);
483 if (of
->start_time
!= AV_NOPTS_VALUE
&& dts
< of
->start_time
)
484 return AVERROR(EAGAIN
);
487 ts_offset
= av_rescale_q(start_time
, AV_TIME_BASE_Q
, pkt
->time_base
);
489 if (pkt
->pts
!= AV_NOPTS_VALUE
)
490 pkt
->pts
-= ts_offset
;
492 if (pkt
->dts
== AV_NOPTS_VALUE
) {
493 pkt
->dts
= av_rescale_q(dts
, AV_TIME_BASE_Q
, pkt
->time_base
);
494 } else if (ost
->st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
495 pkt
->pts
= pkt
->dts
- ts_offset
;
498 pkt
->dts
-= ts_offset
;
500 ms
->streamcopy_started
= 1;
505 int print_sdp(const char *filename
);
507 int print_sdp(const char *filename
)
512 AVFormatContext
**avc
;
514 avc
= av_malloc_array(nb_output_files
, sizeof(*avc
));
516 return AVERROR(ENOMEM
);
517 for (int i
= 0; i
< nb_output_files
; i
++) {
518 Muxer
*mux
= mux_from_of(output_files
[i
]);
520 if (!strcmp(mux
->fc
->oformat
->name
, "rtp")) {
527 av_log(NULL
, AV_LOG_ERROR
, "No output streams in the SDP.\n");
528 ret
= AVERROR(EINVAL
);
532 ret
= av_sdp_create(avc
, j
, sdp
, sizeof(sdp
));
537 printf("SDP:\n%s\n", sdp
);
540 ret
= avio_open2(&sdp_pb
, filename
, AVIO_FLAG_WRITE
, &int_cb
, NULL
);
542 av_log(NULL
, AV_LOG_ERROR
, "Failed to open sdp file '%s'\n", filename
);
546 avio_print(sdp_pb
, sdp
);
547 avio_closep(&sdp_pb
);
555 int mux_check_init(void *arg
)
558 OutputFile
*of
= &mux
->of
;
559 AVFormatContext
*fc
= mux
->fc
;
562 ret
= avformat_write_header(fc
, &mux
->opts
);
564 av_log(mux
, AV_LOG_ERROR
, "Could not write header (incorrect codec "
565 "parameters ?): %s\n", av_err2str(ret
));
568 //assert_avoptions(of->opts);
569 mux
->header_written
= 1;
571 av_dump_format(fc
, of
->index
, fc
->url
, 1);
572 atomic_fetch_add(&nb_output_dumped
, 1);
577 static int bsf_init(MuxStream
*ms
)
579 OutputStream
*ost
= &ms
->ost
;
580 AVBSFContext
*ctx
= ms
->bsf_ctx
;
584 return avcodec_parameters_copy(ost
->st
->codecpar
, ms
->par_in
);
586 ret
= avcodec_parameters_copy(ctx
->par_in
, ms
->par_in
);
590 ctx
->time_base_in
= ost
->st
->time_base
;
592 ret
= av_bsf_init(ctx
);
594 av_log(ms
, AV_LOG_ERROR
, "Error initializing bitstream filter: %s\n",
599 ret
= avcodec_parameters_copy(ost
->st
->codecpar
, ctx
->par_out
);
602 ost
->st
->time_base
= ctx
->time_base_out
;
604 ms
->bsf_pkt
= av_packet_alloc();
606 return AVERROR(ENOMEM
);
611 int of_stream_init(OutputFile
*of
, OutputStream
*ost
,
612 const AVCodecContext
*enc_ctx
)
614 Muxer
*mux
= mux_from_of(of
);
615 MuxStream
*ms
= ms_from_ost(ost
);
619 // use upstream time base unless it has been overridden previously
620 if (ost
->st
->time_base
.num
<= 0 || ost
->st
->time_base
.den
<= 0)
621 ost
->st
->time_base
= av_add_q(enc_ctx
->time_base
, (AVRational
){0, 1});
623 ost
->st
->avg_frame_rate
= enc_ctx
->framerate
;
624 ost
->st
->sample_aspect_ratio
= enc_ctx
->sample_aspect_ratio
;
626 ret
= avcodec_parameters_from_context(ms
->par_in
, enc_ctx
);
628 av_log(ost
, AV_LOG_FATAL
,
629 "Error initializing the output stream codec parameters.\n");
634 /* initialize bitstream filters for the output stream
635 * needs to be done here, because the codec id for streamcopy is not
641 if (ms
->stream_duration
) {
642 ost
->st
->duration
= av_rescale_q(ms
->stream_duration
, ms
->stream_duration_tb
,
646 if (ms
->sch_idx
>= 0)
647 return sch_mux_stream_ready(mux
->sch
, of
->index
, ms
->sch_idx
);
652 static int check_written(OutputFile
*of
)
654 int64_t total_packets_written
= 0;
658 for (int i
= 0; i
< of
->nb_streams
; i
++) {
659 OutputStream
*ost
= of
->streams
[i
];
660 uint64_t packets_written
= atomic_load(&ost
->packets_written
);
662 total_packets_written
+= packets_written
;
665 (ost
->enc
->enc_ctx
->flags
& (AV_CODEC_FLAG_PASS1
| AV_CODEC_FLAG_PASS2
))
666 != AV_CODEC_FLAG_PASS1
)
669 if (!packets_written
&&
670 (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
));
676 if (!total_packets_written
) {
677 int level
= AV_LOG_WARNING
;
679 if (abort_on_flags
& ABORT_ON_FLAG_EMPTY_OUTPUT
) {
680 ret
= err_merge(ret
, AVERROR(EINVAL
));
681 level
= AV_LOG_FATAL
;
684 av_log(of
, level
, "Output file is empty, nothing was encoded%s\n",
685 pass1_used
? "" : "(check -ss / -t / -frames parameters if used)");
691 static void mux_final_stats(Muxer
*mux
)
693 OutputFile
*of
= &mux
->of
;
694 uint64_t total_packets
= 0, total_size
= 0;
695 uint64_t video_size
= 0, audio_size
= 0, subtitle_size
= 0,
696 extra_size
= 0, other_size
= 0;
698 uint8_t overhead
[16] = "unknown";
699 int64_t file_size
= of_filesize(of
);
701 av_log(of
, AV_LOG_VERBOSE
, "Output file #%d (%s):\n",
704 for (int j
= 0; j
< of
->nb_streams
; j
++) {
705 OutputStream
*ost
= of
->streams
[j
];
706 MuxStream
*ms
= ms_from_ost(ost
);
707 const AVCodecParameters
*par
= ost
->st
->codecpar
;
708 const enum AVMediaType type
= par
->codec_type
;
709 const uint64_t s
= ms
->data_size_mux
;
712 case AVMEDIA_TYPE_VIDEO
: video_size
+= s
; break;
713 case AVMEDIA_TYPE_AUDIO
: audio_size
+= s
; break;
714 case AVMEDIA_TYPE_SUBTITLE
: subtitle_size
+= s
; break;
715 default: other_size
+= s
; break;
718 extra_size
+= par
->extradata_size
;
720 total_packets
+= atomic_load(&ost
->packets_written
);
722 av_log(of
, AV_LOG_VERBOSE
, " Output stream #%d:%d (%s): ",
723 of
->index
, j
, av_get_media_type_string(type
));
725 av_log(of
, AV_LOG_VERBOSE
, "%"PRIu64
" frames encoded",
726 ost
->enc
->frames_encoded
);
727 if (type
== AVMEDIA_TYPE_AUDIO
)
728 av_log(of
, AV_LOG_VERBOSE
, " (%"PRIu64
" samples)", ost
->enc
->samples_encoded
);
729 av_log(of
, AV_LOG_VERBOSE
, "; ");
732 av_log(of
, AV_LOG_VERBOSE
, "%"PRIu64
" packets muxed (%"PRIu64
" bytes); ",
733 atomic_load(&ost
->packets_written
), s
);
735 av_log(of
, AV_LOG_VERBOSE
, "\n");
738 av_log(of
, AV_LOG_VERBOSE
, " Total: %"PRIu64
" packets (%"PRIu64
" bytes) muxed\n",
739 total_packets
, total_size
);
741 if (total_size
&& file_size
> 0 && file_size
>= total_size
) {
742 snprintf(overhead
, sizeof(overhead
), "%f%%",
743 100.0 * (file_size
- total_size
) / total_size
);
746 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",
751 subtitle_size
/ 1024.0,
757 int of_write_trailer(OutputFile
*of
)
759 Muxer
*mux
= mux_from_of(of
);
760 AVFormatContext
*fc
= mux
->fc
;
761 int ret
, mux_result
= 0;
763 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
);
770 ret
= av_write_trailer(fc
);
772 av_log(mux
, AV_LOG_ERROR
, "Error writing trailer: %s\n", av_err2str(ret
));
773 mux_result
= err_merge(mux_result
, ret
);
776 mux
->last_filesize
= filesize(fc
->pb
);
778 if (!(fc
->oformat
->flags
& AVFMT_NOFILE
)) {
779 ret
= avio_closep(&fc
->pb
);
781 av_log(mux
, AV_LOG_ERROR
, "Error closing file: %s\n", av_err2str(ret
));
782 mux_result
= err_merge(mux_result
, ret
);
786 mux_final_stats(mux
);
788 // check whether anything was actually written
789 ret
= check_written(of
);
790 mux_result
= err_merge(mux_result
, ret
);
795 static void enc_stats_uninit(EncStats
*es
)
797 for (int i
= 0; i
< es
->nb_components
; i
++)
798 av_freep(&es
->components
[i
].str
);
799 av_freep(&es
->components
);
801 if (es
->lock_initialized
)
802 pthread_mutex_destroy(&es
->lock
);
803 es
->lock_initialized
= 0;
806 static void ost_free(OutputStream
**post
)
808 OutputStream
*ost
= *post
;
813 ms
= ms_from_ost(ost
);
816 fg_free(&ost
->fg_simple
);
819 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
)));
826 avcodec_parameters_free(&ms
->par_in
);
828 av_bsf_free(&ms
->bsf_ctx
);
829 av_packet_free(&ms
->bsf_pkt
);
831 av_packet_free(&ms
->pkt
);
833 av_freep(&ost
->kf
.pts
);
834 av_expr_free(ost
->kf
.pexpr
);
836 av_freep(&ost
->logfile_prefix
);
838 av_freep(&ost
->attachment_filename
);
840 enc_stats_uninit(&ost
->enc_stats_pre
);
841 enc_stats_uninit(&ost
->enc_stats_post
);
842 enc_stats_uninit(&ms
->stats
);
847 static void fc_close(AVFormatContext
**pfc
)
849 AVFormatContext
*fc
= *pfc
;
854 if (!(fc
->oformat
->flags
& AVFMT_NOFILE
))
855 avio_closep(&fc
->pb
);
856 avformat_free_context(fc
);
861 void of_free(OutputFile
**pof
)
863 OutputFile
*of
= *pof
;
868 mux
= mux_from_of(of
);
870 sq_free(&mux
->sq_mux
);
872 for (int i
= 0; i
< of
->nb_streams
; i
++)
873 ost_free(&of
->streams
[i
]);
874 av_freep(&of
->streams
);
876 av_freep(&mux
->sch_stream_idx
);
878 av_dict_free(&mux
->opts
);
879 av_dict_free(&mux
->enc_opts_used
);
881 av_packet_free(&mux
->sq_pkt
);
888 int64_t of_filesize(OutputFile
*of
)
890 Muxer
*mux
= mux_from_of(of
);
891 return atomic_load(&mux
->last_filesize
);