1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include <stdio.h> 20cabdff1aSopenharmony_ci#include <string.h> 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "ffmpeg.h" 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "libavutil/fifo.h" 25cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 26cabdff1aSopenharmony_ci#include "libavutil/log.h" 27cabdff1aSopenharmony_ci#include "libavutil/mem.h" 28cabdff1aSopenharmony_ci#include "libavutil/timestamp.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavcodec/packet.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#include "libavformat/avformat.h" 33cabdff1aSopenharmony_ci#include "libavformat/avio.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_cistatic void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others) 36cabdff1aSopenharmony_ci{ 37cabdff1aSopenharmony_ci int i; 38cabdff1aSopenharmony_ci for (i = 0; i < nb_output_streams; i++) { 39cabdff1aSopenharmony_ci OutputStream *ost2 = output_streams[i]; 40cabdff1aSopenharmony_ci ost2->finished |= ost == ost2 ? this_stream : others; 41cabdff1aSopenharmony_ci } 42cabdff1aSopenharmony_ci} 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_civoid of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, 45cabdff1aSopenharmony_ci int unqueue) 46cabdff1aSopenharmony_ci{ 47cabdff1aSopenharmony_ci AVFormatContext *s = of->ctx; 48cabdff1aSopenharmony_ci AVStream *st = ost->st; 49cabdff1aSopenharmony_ci int ret; 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_ci /* 52cabdff1aSopenharmony_ci * Audio encoders may split the packets -- #frames in != #packets out. 53cabdff1aSopenharmony_ci * But there is no reordering, so we can limit the number of output packets 54cabdff1aSopenharmony_ci * by simply dropping them here. 55cabdff1aSopenharmony_ci * Counting encoded video frames needs to be done separately because of 56cabdff1aSopenharmony_ci * reordering, see do_video_out(). 57cabdff1aSopenharmony_ci * Do not count the packet when unqueued because it has been counted when queued. 58cabdff1aSopenharmony_ci */ 59cabdff1aSopenharmony_ci if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) && !unqueue) { 60cabdff1aSopenharmony_ci if (ost->frame_number >= ost->max_frames) { 61cabdff1aSopenharmony_ci av_packet_unref(pkt); 62cabdff1aSopenharmony_ci return; 63cabdff1aSopenharmony_ci } 64cabdff1aSopenharmony_ci ost->frame_number++; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci if (!of->header_written) { 68cabdff1aSopenharmony_ci AVPacket *tmp_pkt; 69cabdff1aSopenharmony_ci /* the muxer is not initialized yet, buffer the packet */ 70cabdff1aSopenharmony_ci if (!av_fifo_can_write(ost->muxing_queue)) { 71cabdff1aSopenharmony_ci size_t cur_size = av_fifo_can_read(ost->muxing_queue); 72cabdff1aSopenharmony_ci unsigned int are_we_over_size = 73cabdff1aSopenharmony_ci (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold; 74cabdff1aSopenharmony_ci size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX; 75cabdff1aSopenharmony_ci size_t new_size = FFMIN(2 * cur_size, limit); 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci if (new_size <= cur_size) { 78cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, 79cabdff1aSopenharmony_ci "Too many packets buffered for output stream %d:%d.\n", 80cabdff1aSopenharmony_ci ost->file_index, ost->st->index); 81cabdff1aSopenharmony_ci exit_program(1); 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci ret = av_fifo_grow2(ost->muxing_queue, new_size - cur_size); 84cabdff1aSopenharmony_ci if (ret < 0) 85cabdff1aSopenharmony_ci exit_program(1); 86cabdff1aSopenharmony_ci } 87cabdff1aSopenharmony_ci ret = av_packet_make_refcounted(pkt); 88cabdff1aSopenharmony_ci if (ret < 0) 89cabdff1aSopenharmony_ci exit_program(1); 90cabdff1aSopenharmony_ci tmp_pkt = av_packet_alloc(); 91cabdff1aSopenharmony_ci if (!tmp_pkt) 92cabdff1aSopenharmony_ci exit_program(1); 93cabdff1aSopenharmony_ci av_packet_move_ref(tmp_pkt, pkt); 94cabdff1aSopenharmony_ci ost->muxing_queue_data_size += tmp_pkt->size; 95cabdff1aSopenharmony_ci av_fifo_write(ost->muxing_queue, &tmp_pkt, 1); 96cabdff1aSopenharmony_ci return; 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP) || 100cabdff1aSopenharmony_ci (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) 101cabdff1aSopenharmony_ci pkt->pts = pkt->dts = AV_NOPTS_VALUE; 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { 104cabdff1aSopenharmony_ci if (ost->frame_rate.num && ost->is_cfr) { 105cabdff1aSopenharmony_ci if (pkt->duration > 0) 106cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); 107cabdff1aSopenharmony_ci pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), 108cabdff1aSopenharmony_ci ost->mux_timebase); 109cabdff1aSopenharmony_ci } 110cabdff1aSopenharmony_ci } 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base); 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { 115cabdff1aSopenharmony_ci if (pkt->dts != AV_NOPTS_VALUE && 116cabdff1aSopenharmony_ci pkt->pts != AV_NOPTS_VALUE && 117cabdff1aSopenharmony_ci pkt->dts > pkt->pts) { 118cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n", 119cabdff1aSopenharmony_ci pkt->dts, pkt->pts, 120cabdff1aSopenharmony_ci ost->file_index, ost->st->index); 121cabdff1aSopenharmony_ci pkt->pts = 122cabdff1aSopenharmony_ci pkt->dts = pkt->pts + pkt->dts + ost->last_mux_dts + 1 123cabdff1aSopenharmony_ci - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1) 124cabdff1aSopenharmony_ci - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1); 125cabdff1aSopenharmony_ci } 126cabdff1aSopenharmony_ci if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) && 127cabdff1aSopenharmony_ci pkt->dts != AV_NOPTS_VALUE && 128cabdff1aSopenharmony_ci ost->last_mux_dts != AV_NOPTS_VALUE) { 129cabdff1aSopenharmony_ci int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); 130cabdff1aSopenharmony_ci if (pkt->dts < max) { 131cabdff1aSopenharmony_ci int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; 132cabdff1aSopenharmony_ci if (exit_on_error) 133cabdff1aSopenharmony_ci loglevel = AV_LOG_ERROR; 134cabdff1aSopenharmony_ci av_log(s, loglevel, "Non-monotonous DTS in output stream " 135cabdff1aSopenharmony_ci "%d:%d; previous: %"PRId64", current: %"PRId64"; ", 136cabdff1aSopenharmony_ci ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); 137cabdff1aSopenharmony_ci if (exit_on_error) { 138cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_FATAL, "aborting.\n"); 139cabdff1aSopenharmony_ci exit_program(1); 140cabdff1aSopenharmony_ci } 141cabdff1aSopenharmony_ci av_log(s, loglevel, "changing to %"PRId64". This may result " 142cabdff1aSopenharmony_ci "in incorrect timestamps in the output file.\n", 143cabdff1aSopenharmony_ci max); 144cabdff1aSopenharmony_ci if (pkt->pts >= pkt->dts) 145cabdff1aSopenharmony_ci pkt->pts = FFMAX(pkt->pts, max); 146cabdff1aSopenharmony_ci pkt->dts = max; 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci } 149cabdff1aSopenharmony_ci } 150cabdff1aSopenharmony_ci ost->last_mux_dts = pkt->dts; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci ost->data_size += pkt->size; 153cabdff1aSopenharmony_ci ost->packets_written++; 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci pkt->stream_index = ost->index; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci if (debug_ts) { 158cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_INFO, "muxer <- type:%s " 159cabdff1aSopenharmony_ci "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n", 160cabdff1aSopenharmony_ci av_get_media_type_string(ost->enc_ctx->codec_type), 161cabdff1aSopenharmony_ci av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), 162cabdff1aSopenharmony_ci av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base), 163cabdff1aSopenharmony_ci av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base), 164cabdff1aSopenharmony_ci pkt->size 165cabdff1aSopenharmony_ci ); 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci ret = av_interleaved_write_frame(s, pkt); 169cabdff1aSopenharmony_ci if (ret < 0) { 170cabdff1aSopenharmony_ci print_error("av_interleaved_write_frame()", ret); 171cabdff1aSopenharmony_ci main_return_code = 1; 172cabdff1aSopenharmony_ci close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED); 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci} 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_cistatic int print_sdp(void) 177cabdff1aSopenharmony_ci{ 178cabdff1aSopenharmony_ci char sdp[16384]; 179cabdff1aSopenharmony_ci int i; 180cabdff1aSopenharmony_ci int j, ret; 181cabdff1aSopenharmony_ci AVIOContext *sdp_pb; 182cabdff1aSopenharmony_ci AVFormatContext **avc; 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci for (i = 0; i < nb_output_files; i++) { 185cabdff1aSopenharmony_ci if (!output_files[i]->header_written) 186cabdff1aSopenharmony_ci return 0; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci avc = av_malloc_array(nb_output_files, sizeof(*avc)); 190cabdff1aSopenharmony_ci if (!avc) 191cabdff1aSopenharmony_ci exit_program(1); 192cabdff1aSopenharmony_ci for (i = 0, j = 0; i < nb_output_files; i++) { 193cabdff1aSopenharmony_ci if (!strcmp(output_files[i]->ctx->oformat->name, "rtp")) { 194cabdff1aSopenharmony_ci avc[j] = output_files[i]->ctx; 195cabdff1aSopenharmony_ci j++; 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci if (!j) { 200cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n"); 201cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 202cabdff1aSopenharmony_ci goto fail; 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci 205cabdff1aSopenharmony_ci ret = av_sdp_create(avc, j, sdp, sizeof(sdp)); 206cabdff1aSopenharmony_ci if (ret < 0) 207cabdff1aSopenharmony_ci goto fail; 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci if (!sdp_filename) { 210cabdff1aSopenharmony_ci printf("SDP:\n%s\n", sdp); 211cabdff1aSopenharmony_ci fflush(stdout); 212cabdff1aSopenharmony_ci } else { 213cabdff1aSopenharmony_ci ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL); 214cabdff1aSopenharmony_ci if (ret < 0) { 215cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename); 216cabdff1aSopenharmony_ci goto fail; 217cabdff1aSopenharmony_ci } 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci avio_print(sdp_pb, sdp); 220cabdff1aSopenharmony_ci avio_closep(&sdp_pb); 221cabdff1aSopenharmony_ci av_freep(&sdp_filename); 222cabdff1aSopenharmony_ci } 223cabdff1aSopenharmony_ci 224cabdff1aSopenharmony_cifail: 225cabdff1aSopenharmony_ci av_freep(&avc); 226cabdff1aSopenharmony_ci return ret; 227cabdff1aSopenharmony_ci} 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci/* open the muxer when all the streams are initialized */ 230cabdff1aSopenharmony_ciint of_check_init(OutputFile *of) 231cabdff1aSopenharmony_ci{ 232cabdff1aSopenharmony_ci int ret, i; 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_ci for (i = 0; i < of->ctx->nb_streams; i++) { 235cabdff1aSopenharmony_ci OutputStream *ost = output_streams[of->ost_index + i]; 236cabdff1aSopenharmony_ci if (!ost->initialized) 237cabdff1aSopenharmony_ci return 0; 238cabdff1aSopenharmony_ci } 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci ret = avformat_write_header(of->ctx, &of->opts); 241cabdff1aSopenharmony_ci if (ret < 0) { 242cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, 243cabdff1aSopenharmony_ci "Could not write header for output file #%d " 244cabdff1aSopenharmony_ci "(incorrect codec parameters ?): %s\n", 245cabdff1aSopenharmony_ci of->index, av_err2str(ret)); 246cabdff1aSopenharmony_ci return ret; 247cabdff1aSopenharmony_ci } 248cabdff1aSopenharmony_ci //assert_avoptions(of->opts); 249cabdff1aSopenharmony_ci of->header_written = 1; 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_ci av_dump_format(of->ctx, of->index, of->ctx->url, 1); 252cabdff1aSopenharmony_ci nb_output_dumped++; 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_ci if (sdp_filename || want_sdp) { 255cabdff1aSopenharmony_ci ret = print_sdp(); 256cabdff1aSopenharmony_ci if (ret < 0) { 257cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n"); 258cabdff1aSopenharmony_ci return ret; 259cabdff1aSopenharmony_ci } 260cabdff1aSopenharmony_ci } 261cabdff1aSopenharmony_ci 262cabdff1aSopenharmony_ci /* flush the muxing queues */ 263cabdff1aSopenharmony_ci for (i = 0; i < of->ctx->nb_streams; i++) { 264cabdff1aSopenharmony_ci OutputStream *ost = output_streams[of->ost_index + i]; 265cabdff1aSopenharmony_ci AVPacket *pkt; 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci /* try to improve muxing time_base (only possible if nothing has been written yet) */ 268cabdff1aSopenharmony_ci if (!av_fifo_can_read(ost->muxing_queue)) 269cabdff1aSopenharmony_ci ost->mux_timebase = ost->st->time_base; 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci while (av_fifo_read(ost->muxing_queue, &pkt, 1) >= 0) { 272cabdff1aSopenharmony_ci ost->muxing_queue_data_size -= pkt->size; 273cabdff1aSopenharmony_ci of_write_packet(of, pkt, ost, 1); 274cabdff1aSopenharmony_ci av_packet_free(&pkt); 275cabdff1aSopenharmony_ci } 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci return 0; 279cabdff1aSopenharmony_ci} 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_ciint of_write_trailer(OutputFile *of) 282cabdff1aSopenharmony_ci{ 283cabdff1aSopenharmony_ci int ret; 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_ci if (!of->header_written) { 286cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, 287cabdff1aSopenharmony_ci "Nothing was written into output file %d (%s), because " 288cabdff1aSopenharmony_ci "at least one of its streams received no packets.\n", 289cabdff1aSopenharmony_ci of->index, of->ctx->url); 290cabdff1aSopenharmony_ci return AVERROR(EINVAL); 291cabdff1aSopenharmony_ci } 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci ret = av_write_trailer(of->ctx); 294cabdff1aSopenharmony_ci if (ret < 0) { 295cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", of->ctx->url, av_err2str(ret)); 296cabdff1aSopenharmony_ci return ret; 297cabdff1aSopenharmony_ci } 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci return 0; 300cabdff1aSopenharmony_ci} 301cabdff1aSopenharmony_ci 302cabdff1aSopenharmony_civoid of_close(OutputFile **pof) 303cabdff1aSopenharmony_ci{ 304cabdff1aSopenharmony_ci OutputFile *of = *pof; 305cabdff1aSopenharmony_ci AVFormatContext *s; 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci if (!of) 308cabdff1aSopenharmony_ci return; 309cabdff1aSopenharmony_ci 310cabdff1aSopenharmony_ci s = of->ctx; 311cabdff1aSopenharmony_ci if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE)) 312cabdff1aSopenharmony_ci avio_closep(&s->pb); 313cabdff1aSopenharmony_ci avformat_free_context(s); 314cabdff1aSopenharmony_ci av_dict_free(&of->opts); 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_ci av_freep(pof); 317cabdff1aSopenharmony_ci} 318