3 * Copyright (c) 2011 Martin Storsjo
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/mathematics.h"
23 #include "libavutil/mem.h"
24 #include "libavutil/opt.h"
26 #include "avio_internal.h"
29 typedef struct MuxChain
{
31 AVFormatContext
*mpegts_ctx
;
32 AVFormatContext
*rtp_ctx
;
34 AVDictionary
* mpegts_muxer_options
;
35 AVDictionary
* rtp_muxer_options
;
38 static int rtp_mpegts_write_close(AVFormatContext
*s
)
40 MuxChain
*chain
= s
->priv_data
;
42 if (chain
->mpegts_ctx
) {
43 av_write_trailer(chain
->mpegts_ctx
);
44 ffio_free_dyn_buf(&chain
->mpegts_ctx
->pb
);
45 avformat_free_context(chain
->mpegts_ctx
);
48 av_write_trailer(chain
->rtp_ctx
);
49 avformat_free_context(chain
->rtp_ctx
);
52 av_packet_free(&chain
->pkt
);
57 static int rtp_mpegts_write_header(AVFormatContext
*s
)
59 MuxChain
*chain
= s
->priv_data
;
60 AVFormatContext
*mpegts_ctx
= NULL
, *rtp_ctx
= NULL
;
61 const AVOutputFormat
*mpegts_format
= av_guess_format("mpegts", NULL
, NULL
);
62 const AVOutputFormat
*rtp_format
= av_guess_format("rtp", NULL
, NULL
);
63 int i
, ret
= AVERROR(ENOMEM
);
65 AVDictionary
*mpegts_muxer_options
= NULL
;
66 AVDictionary
*rtp_muxer_options
= NULL
;
68 if (!mpegts_format
|| !rtp_format
)
69 return AVERROR(ENOSYS
);
70 mpegts_ctx
= avformat_alloc_context();
72 return AVERROR(ENOMEM
);
73 chain
->pkt
= av_packet_alloc();
76 mpegts_ctx
->oformat
= mpegts_format
;
77 mpegts_ctx
->max_delay
= s
->max_delay
;
78 av_dict_copy(&mpegts_ctx
->metadata
, s
->metadata
, 0);
79 for (i
= 0; i
< s
->nb_streams
; i
++) {
80 AVStream
* st
= avformat_new_stream(mpegts_ctx
, NULL
);
83 st
->time_base
= s
->streams
[i
]->time_base
;
84 st
->sample_aspect_ratio
= s
->streams
[i
]->sample_aspect_ratio
;
85 st
->id
= s
->streams
[i
]->id
;
86 avcodec_parameters_copy(st
->codecpar
, s
->streams
[i
]->codecpar
);
88 if ((ret
= avio_open_dyn_buf(&mpegts_ctx
->pb
)) < 0)
91 av_dict_copy(&mpegts_muxer_options
, chain
->mpegts_muxer_options
, 0);
93 ret
= avformat_write_header(mpegts_ctx
, &mpegts_muxer_options
);
94 av_dict_free(&mpegts_muxer_options
);
98 for (i
= 0; i
< s
->nb_streams
; i
++)
99 s
->streams
[i
]->time_base
= mpegts_ctx
->streams
[i
]->time_base
;
101 chain
->mpegts_ctx
= mpegts_ctx
;
104 rtp_ctx
= avformat_alloc_context();
106 ret
= AVERROR(ENOMEM
);
109 rtp_ctx
->oformat
= rtp_format
;
110 st
= avformat_new_stream(rtp_ctx
, NULL
);
112 ret
= AVERROR(ENOMEM
);
115 st
->time_base
.num
= 1;
116 st
->time_base
.den
= 90000;
117 st
->codecpar
->codec_id
= AV_CODEC_ID_MPEG2TS
;
119 av_dict_copy(&rtp_muxer_options
, chain
->rtp_muxer_options
, 0);
120 ret
= avformat_write_header(rtp_ctx
, &rtp_muxer_options
);
121 av_dict_free(&rtp_muxer_options
);
125 chain
->rtp_ctx
= rtp_ctx
;
131 ffio_free_dyn_buf(&mpegts_ctx
->pb
);
132 av_dict_free(&mpegts_ctx
->metadata
);
133 avformat_free_context(mpegts_ctx
);
135 avformat_free_context(rtp_ctx
);
136 rtp_mpegts_write_close(s
);
140 static int rtp_mpegts_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
142 MuxChain
*chain
= s
->priv_data
;
145 AVPacket
*local_pkt
= chain
->pkt
;
147 if (!chain
->mpegts_ctx
->pb
) {
148 if ((ret
= avio_open_dyn_buf(&chain
->mpegts_ctx
->pb
)) < 0)
151 if ((ret
= av_write_frame(chain
->mpegts_ctx
, pkt
)) < 0)
153 size
= avio_close_dyn_buf(chain
->mpegts_ctx
->pb
, &buf
);
154 chain
->mpegts_ctx
->pb
= NULL
;
159 av_packet_unref(local_pkt
);
160 local_pkt
->data
= buf
;
161 local_pkt
->size
= size
;
162 local_pkt
->stream_index
= 0;
163 if (pkt
->pts
!= AV_NOPTS_VALUE
)
164 local_pkt
->pts
= av_rescale_q(pkt
->pts
,
165 s
->streams
[pkt
->stream_index
]->time_base
,
166 chain
->rtp_ctx
->streams
[0]->time_base
);
167 if (pkt
->dts
!= AV_NOPTS_VALUE
)
168 local_pkt
->dts
= av_rescale_q(pkt
->dts
,
169 s
->streams
[pkt
->stream_index
]->time_base
,
170 chain
->rtp_ctx
->streams
[0]->time_base
);
171 ret
= av_write_frame(chain
->rtp_ctx
, local_pkt
);
177 #define OFFSET(x) offsetof(MuxChain, x)
178 #define E AV_OPT_FLAG_ENCODING_PARAM
179 static const AVOption options
[] = {
180 { "mpegts_muxer_options", "set list of options for the MPEG-TS muxer", OFFSET(mpegts_muxer_options
), AV_OPT_TYPE_DICT
, {.str
= NULL
}, 0, 0, E
},
181 { "rtp_muxer_options", "set list of options for the RTP muxer", OFFSET(rtp_muxer_options
), AV_OPT_TYPE_DICT
, {.str
= NULL
}, 0, 0, E
},
185 static const AVClass rtp_mpegts_class
= {
186 .class_name
= "rtp_mpegts muxer",
187 .item_name
= av_default_item_name
,
189 .version
= LIBAVUTIL_VERSION_INT
,
192 const FFOutputFormat ff_rtp_mpegts_muxer
= {
193 .p
.name
= "rtp_mpegts",
194 .p
.long_name
= NULL_IF_CONFIG_SMALL("RTP/mpegts output format"),
195 .priv_data_size
= sizeof(MuxChain
),
196 .p
.audio_codec
= AV_CODEC_ID_AAC
,
197 .p
.video_codec
= AV_CODEC_ID_MPEG4
,
198 .write_header
= rtp_mpegts_write_header
,
199 .write_packet
= rtp_mpegts_write_packet
,
200 .write_trailer
= rtp_mpegts_write_close
,
201 .p
.priv_class
= &rtp_mpegts_class
,