1 /*****************************************************************************
2 * mux.c: muxer using libavformat
3 *****************************************************************************
4 * Copyright (C) 2006 VLC authors and VideoLAN
5 * $Id: 48878c712b3cea59debcc7390a3f4dfc92f96ab5 $
6 *
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
23
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_block.h>
34 #include <vlc_sout.h>
35
36 #include <libavformat/avformat.h>
37
38 #include "avformat.h"
39 #include "../../codec/avcodec/avcodec.h"
40 #include "../../codec/avcodec/avcommon.h"
41 #include "../xiph.h"
42
43
44 //#define AVFORMAT_DEBUG 1
45
46 static const char *const ppsz_mux_options[] = {
47 "mux", "options", "reset-ts", NULL
48 };
49
50 /*****************************************************************************
51 * mux_sys_t: mux descriptor
52 *****************************************************************************/
53 struct sout_mux_sys_t
54 {
55 AVIOContext *io;
56 int io_buffer_size;
57 uint8_t *io_buffer;
58
59 AVFormatContext *oc;
60
61 bool b_write_header;
62 bool b_write_keyframe;
63 bool b_error;
64 #if LIBAVFORMAT_VERSION_CHECK( 57, 7, 0, 40, 100 )
65 bool b_header_done;
66 #endif
67 };
68
69 /*****************************************************************************
70 * Local prototypes
71 *****************************************************************************/
72 static int Control ( sout_mux_t *, int, va_list );
73 static int AddStream( sout_mux_t *, sout_input_t * );
74 static void DelStream( sout_mux_t *, sout_input_t * );
75 static int Mux ( sout_mux_t * );
76
77 static int IOWrite( void *opaque, uint8_t *buf, int buf_size );
78 static int64_t IOSeek( void *opaque, int64_t offset, int whence );
79 #if LIBAVFORMAT_VERSION_CHECK( 57, 7, 0, 40, 100 )
80 static int IOWriteTyped(void *opaque, uint8_t *buf, int buf_size,
81 enum AVIODataMarkerType type, int64_t time);
82 #endif
83
84 /*****************************************************************************
85 * Open
86 *****************************************************************************/
avformat_OpenMux(vlc_object_t * p_this)87 int avformat_OpenMux( vlc_object_t *p_this )
88 {
89 AVOutputFormat *file_oformat;
90 sout_mux_t *p_mux = (sout_mux_t*)p_this;
91 bool dummy = !strcmp( p_mux->p_access->psz_access, "dummy");
92
93 if( dummy && strlen(p_mux->p_access->psz_path)
94 >= sizeof (((AVFormatContext *)NULL)->filename) )
95 return VLC_EGENERIC;
96
97 msg_Dbg( p_mux, "using %s %s", AVPROVIDER(LIBAVFORMAT), LIBAVFORMAT_IDENT );
98
99 vlc_init_avformat(p_this);
100
101 config_ChainParse( p_mux, "sout-avformat-", ppsz_mux_options, p_mux->p_cfg );
102
103 /* Find the requested muxer */
104 char *psz_mux = var_InheritString( p_mux, "sout-avformat-mux" );
105 if( psz_mux )
106 {
107 file_oformat = av_guess_format( psz_mux, NULL, NULL );
108 free( psz_mux );
109 }
110 else
111 {
112 file_oformat =
113 av_guess_format( NULL, p_mux->p_access->psz_path, NULL);
114 }
115 if (!file_oformat)
116 {
117 msg_Err( p_mux, "unable for find a suitable output format" );
118 return VLC_EGENERIC;
119 }
120
121 sout_mux_sys_t *p_sys = malloc( sizeof( sout_mux_sys_t ) );
122 if( unlikely(p_sys == NULL) )
123 return VLC_ENOMEM;
124
125 p_mux->p_sys = p_sys;
126 p_sys->oc = avformat_alloc_context();
127 p_sys->oc->oformat = file_oformat;
128 /* If we use dummy access, let avformat write output */
129 if( dummy )
130 strcpy( p_sys->oc->filename, p_mux->p_access->psz_path );
131
132 /* Create I/O wrapper */
133 p_sys->io_buffer_size = 10 * 1024 * 1024; /* FIXME */
134 p_sys->io_buffer = malloc( p_sys->io_buffer_size );
135
136 bool b_can_seek;
137 if( sout_AccessOutControl( p_mux->p_access, ACCESS_OUT_CAN_SEEK, &b_can_seek ) )
138 b_can_seek = false;
139 p_sys->io = avio_alloc_context(
140 p_sys->io_buffer, p_sys->io_buffer_size,
141 1, p_mux, NULL, IOWrite, b_can_seek ? IOSeek : NULL );
142
143 p_sys->oc->pb = p_sys->io;
144 p_sys->oc->nb_streams = 0;
145
146 p_sys->b_write_header = true;
147 p_sys->b_write_keyframe = false;
148 p_sys->b_error = false;
149 #if LIBAVFORMAT_VERSION_CHECK( 57, 7, 0, 40, 100 )
150 p_sys->io->write_data_type = IOWriteTyped;
151 p_sys->b_header_done = false;
152 #endif
153 if( var_GetBool( p_mux, "sout-avformat-reset-ts" ) )
154 p_sys->oc->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
155
156 /* Fill p_mux fields */
157 p_mux->pf_control = Control;
158 p_mux->pf_addstream = AddStream;
159 p_mux->pf_delstream = DelStream;
160 p_mux->pf_mux = Mux;
161
162 return VLC_SUCCESS;
163 }
164
165 /*****************************************************************************
166 * Close
167 *****************************************************************************/
avformat_CloseMux(vlc_object_t * p_this)168 void avformat_CloseMux( vlc_object_t *p_this )
169 {
170 sout_mux_t *p_mux = (sout_mux_t*)p_this;
171 sout_mux_sys_t *p_sys = p_mux->p_sys;
172
173 if( !p_sys->b_write_header && !p_sys->b_error && av_write_trailer( p_sys->oc ) < 0 )
174 {
175 msg_Err( p_mux, "could not write trailer" );
176 }
177
178 avformat_free_context(p_sys->oc);
179 av_free(p_sys->io);
180
181 free( p_sys->io_buffer );
182 free( p_sys );
183 }
184
185 /*****************************************************************************
186 * AddStream
187 *****************************************************************************/
AddStream(sout_mux_t * p_mux,sout_input_t * p_input)188 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
189 {
190 sout_mux_sys_t *p_sys = p_mux->p_sys;
191 const es_format_t *fmt = p_input->p_fmt;
192 unsigned i_codec_id;
193
194 msg_Dbg( p_mux, "adding input" );
195
196 if( !GetFfmpegCodec( fmt->i_cat, fmt->i_codec, &i_codec_id, NULL )
197 || i_codec_id == AV_CODEC_ID_NONE )
198 {
199 msg_Dbg( p_mux, "couldn't find codec for fourcc '%4.4s'",
200 (char *)&fmt->i_codec );
201 return VLC_EGENERIC;
202 }
203
204 unsigned opus_size[XIPH_MAX_HEADER_COUNT];
205 const void *opus_packet[XIPH_MAX_HEADER_COUNT];
206 if( fmt->i_codec == VLC_CODEC_OPUS )
207 {
208 unsigned count;
209 /* Only transmits the first packet (OpusHead) */
210 if( xiph_SplitHeaders(opus_size, opus_packet, &count, fmt->i_extra, fmt->p_extra ) ) {
211 count = 0;
212 }
213 if (count != 2 || opus_size[0] < 19) {
214 msg_Err(p_mux, "Invalid Opus header");
215 return VLC_EGENERIC;
216 }
217 }
218 else if( fmt->i_codec == VLC_CODEC_MPGA && fmt->i_profile == 3 )
219 {
220 i_codec_id = AV_CODEC_ID_MP3;
221 }
222
223 if( fmt->i_cat != VIDEO_ES && fmt->i_cat != AUDIO_ES)
224 {
225 msg_Warn( p_mux, "Unhandled ES category" );
226 return VLC_EGENERIC;
227 }
228
229 /* */
230 p_input->p_sys = malloc( sizeof( int ) );
231 if( unlikely(p_input->p_sys == NULL) )
232 return VLC_ENOMEM;
233
234 *((int *)p_input->p_sys) = p_sys->oc->nb_streams;
235
236 /* */
237 AVStream *stream = avformat_new_stream( p_sys->oc, NULL);
238 if( !stream )
239 {
240 free( p_input->p_sys );
241 return VLC_EGENERIC;
242 }
243
244 #if (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 5, 0))
245 AVCodecParameters *codecpar = stream->codecpar;
246 #else
247 AVCodecContext *codecpar = stream->codec;
248 #endif
249
250 unsigned int i_bitrate = fmt->i_bitrate;
251 unsigned int i_frame_rate = fmt->video.i_frame_rate;
252 unsigned int i_frame_rate_base = fmt->video.i_frame_rate_base;
253 switch( fmt->i_cat )
254 {
255 case AUDIO_ES:
256 codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
257 codecpar->channels = fmt->audio.i_channels;
258 codecpar->sample_rate = fmt->audio.i_rate;
259 stream->time_base = (AVRational){1, codecpar->sample_rate};
260 if (fmt->i_bitrate == 0) {
261 msg_Warn( p_mux, "Missing audio bitrate, assuming 64k" );
262 i_bitrate = 64000;
263 }
264 break;
265
266 case VIDEO_ES:
267 if( !fmt->video.i_frame_rate || !fmt->video.i_frame_rate_base ) {
268 msg_Warn( p_mux, "Missing frame rate, assuming 25fps" );
269 i_frame_rate = 25;
270 i_frame_rate_base = 1;
271 } else
272 msg_Dbg( p_mux, "Muxing framerate will be %d/%d = %.2f fps",
273 fmt->video.i_frame_rate,
274 fmt->video.i_frame_rate_base,
275 (double)fmt->video.i_frame_rate/(double)fmt->video.i_frame_rate_base );
276
277 codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
278 codecpar->width = fmt->video.i_visible_width;
279 codecpar->height = fmt->video.i_visible_height;
280 av_reduce( &codecpar->sample_aspect_ratio.num,
281 &codecpar->sample_aspect_ratio.den,
282 fmt->video.i_sar_num,
283 fmt->video.i_sar_den, 1 << 30 /* something big */ );
284 msg_Dbg(p_mux, "Muxing aspect ratio will be %d/%d",
285 fmt->video.i_sar_num, fmt->video.i_sar_den);
286 stream->sample_aspect_ratio.den = codecpar->sample_aspect_ratio.den;
287 stream->sample_aspect_ratio.num = codecpar->sample_aspect_ratio.num;
288 stream->time_base.den = i_frame_rate;
289 stream->time_base.num = i_frame_rate_base;
290 if (fmt->i_bitrate == 0) {
291 msg_Warn( p_mux, "Missing video bitrate, assuming 512k" );
292 i_bitrate = 512000;
293 } else
294 msg_Dbg( p_mux, "Muxing video bitrate will be %d", fmt->i_bitrate );
295 break;
296
297 default:
298 vlc_assert_unreachable();
299 }
300
301 codecpar->bit_rate = i_bitrate;
302 codecpar->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id );
303 if( !codecpar->codec_tag && i_codec_id == AV_CODEC_ID_MP2 )
304 {
305 i_codec_id = AV_CODEC_ID_MP3;
306 codecpar->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id );
307 }
308 codecpar->codec_id = i_codec_id;
309
310 if( fmt->i_extra )
311 {
312 if( fmt->i_codec == VLC_CODEC_OPUS )
313 {
314 codecpar->extradata_size = opus_size[0];
315 codecpar->extradata = av_malloc( opus_size[0] );
316 memcpy( codecpar->extradata, opus_packet[0], opus_size[0] );
317 }
318 else
319 {
320 codecpar->extradata_size = fmt->i_extra;
321 codecpar->extradata = av_malloc( fmt->i_extra );
322 memcpy( codecpar->extradata, fmt->p_extra, fmt->i_extra );
323 }
324 }
325
326 return VLC_SUCCESS;
327 }
328
329 /*****************************************************************************
330 * DelStream
331 *****************************************************************************/
DelStream(sout_mux_t * p_mux,sout_input_t * p_input)332 static void DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
333 {
334 msg_Dbg( p_mux, "removing input" );
335 free( p_input->p_sys );
336 }
337
MuxBlock(sout_mux_t * p_mux,sout_input_t * p_input)338 static int MuxBlock( sout_mux_t *p_mux, sout_input_t *p_input )
339 {
340 sout_mux_sys_t *p_sys = p_mux->p_sys;
341 block_t *p_data = block_FifoGet( p_input->p_fifo );
342 int i_stream = *((int *)p_input->p_sys);
343 AVStream *p_stream = p_sys->oc->streams[i_stream];
344 AVPacket pkt;
345
346 memset( &pkt, 0, sizeof(AVPacket) );
347
348 av_init_packet(&pkt);
349 pkt.data = p_data->p_buffer;
350 pkt.size = p_data->i_buffer;
351 pkt.stream_index = i_stream;
352
353 if( p_data->i_flags & BLOCK_FLAG_TYPE_I )
354 {
355 #ifdef AVFMT_ALLOW_FLUSH
356 /* Make sure we don't inadvertedly mark buffered data as keyframes. */
357 if( p_sys->oc->oformat->flags & AVFMT_ALLOW_FLUSH )
358 av_write_frame( p_sys->oc, NULL );
359 #endif
360
361 p_sys->b_write_keyframe = true;
362 pkt.flags |= AV_PKT_FLAG_KEY;
363 }
364
365 if( p_data->i_pts > 0 )
366 pkt.pts = p_data->i_pts * p_stream->time_base.den /
367 CLOCK_FREQ / p_stream->time_base.num;
368 if( p_data->i_dts > 0 )
369 pkt.dts = p_data->i_dts * p_stream->time_base.den /
370 CLOCK_FREQ / p_stream->time_base.num;
371
372 /* this is another hack to prevent libavformat from triggering the "non monotone timestamps" check in avformat/utils.c */
373 p_stream->cur_dts = ( p_data->i_dts * p_stream->time_base.den /
374 CLOCK_FREQ / p_stream->time_base.num ) - 1;
375
376 if( av_write_frame( p_sys->oc, &pkt ) < 0 )
377 {
378 msg_Err( p_mux, "could not write frame (pts: %"PRId64", dts: %"PRId64") "
379 "(pkt pts: %"PRId64", dts: %"PRId64")",
380 p_data->i_pts, p_data->i_dts, pkt.pts, pkt.dts );
381 block_Release( p_data );
382 return VLC_EGENERIC;
383 }
384
385 block_Release( p_data );
386 return VLC_SUCCESS;
387 }
388
389 #if LIBAVFORMAT_VERSION_CHECK( 57, 7, 0, 40, 100 )
IOWriteTyped(void * opaque,uint8_t * buf,int buf_size,enum AVIODataMarkerType type,int64_t time)390 int IOWriteTyped(void *opaque, uint8_t *buf, int buf_size,
391 enum AVIODataMarkerType type, int64_t time)
392 {
393 VLC_UNUSED(time);
394
395 sout_mux_t *p_mux = opaque;
396 sout_mux_sys_t *p_sys = p_mux->p_sys;
397 if ( !p_sys->b_header_done && type != AVIO_DATA_MARKER_HEADER )
398 p_sys->b_header_done = true;
399 return IOWrite(opaque, buf, buf_size);
400 }
401 #endif
402
403 /*****************************************************************************
404 * Mux: multiplex available data in input fifos
405 *****************************************************************************/
Mux(sout_mux_t * p_mux)406 static int Mux( sout_mux_t *p_mux )
407 {
408 sout_mux_sys_t *p_sys = p_mux->p_sys;
409
410 if( p_sys->b_error ) return VLC_EGENERIC;
411
412 if( p_sys->b_write_header )
413 {
414 int error;
415 msg_Dbg( p_mux, "writing header" );
416
417 char *psz_opts = var_GetNonEmptyString( p_mux, "sout-avformat-options" );
418 AVDictionary *options = NULL;
419 if (psz_opts) {
420 vlc_av_get_options(psz_opts, &options);
421 free(psz_opts);
422 }
423 av_dict_set( &p_sys->oc->metadata, "encoding_tool", "VLC "VERSION, 0 );
424 error = avformat_write_header( p_sys->oc, options ? &options : NULL);
425 AVDictionaryEntry *t = NULL;
426 while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) {
427 msg_Err( p_mux, "Unknown option \"%s\"", t->key );
428 }
429 av_dict_free(&options);
430 if( error < 0 )
431 {
432 msg_Err( p_mux, "could not write header: %s",
433 vlc_strerror_c(AVUNERROR(error)) );
434 p_sys->b_write_header = false;
435 p_sys->b_error = true;
436 return VLC_EGENERIC;
437 }
438
439 avio_flush( p_sys->oc->pb );
440 p_sys->b_write_header = false;
441 }
442
443 for( ;; )
444 {
445 mtime_t i_dts;
446
447 int i_stream = sout_MuxGetStream( p_mux, 1, &i_dts );
448 if( i_stream < 0 )
449 return VLC_SUCCESS;
450
451 MuxBlock( p_mux, p_mux->pp_inputs[i_stream] );
452 }
453
454 return VLC_SUCCESS;
455 }
456
457 /*****************************************************************************
458 * Control:
459 *****************************************************************************/
Control(sout_mux_t * p_mux,int i_query,va_list args)460 static int Control( sout_mux_t *p_mux, int i_query, va_list args )
461 {
462 bool *pb_bool;
463
464 switch( i_query )
465 {
466 case MUX_CAN_ADD_STREAM_WHILE_MUXING:
467 pb_bool = va_arg( args, bool * );
468 *pb_bool = false;
469 return VLC_SUCCESS;
470
471 case MUX_GET_ADD_STREAM_WAIT:
472 pb_bool = va_arg( args, bool * );
473 *pb_bool = true;
474 return VLC_SUCCESS;
475
476 case MUX_GET_MIME:
477 {
478 char **ppsz = va_arg( args, char ** );
479 *ppsz = strdup( p_mux->p_sys->oc->oformat->mime_type );
480 return VLC_SUCCESS;
481 }
482
483 default:
484 return VLC_EGENERIC;
485 }
486 }
487
488 /*****************************************************************************
489 * I/O wrappers for libavformat
490 *****************************************************************************/
IOWrite(void * opaque,uint8_t * buf,int buf_size)491 static int IOWrite( void *opaque, uint8_t *buf, int buf_size )
492 {
493 sout_mux_t *p_mux = opaque;
494 sout_mux_sys_t *p_sys = p_mux->p_sys;
495 int i_ret;
496
497 #ifdef AVFORMAT_DEBUG
498 msg_Dbg( p_mux, "IOWrite %i bytes", buf_size );
499 #endif
500
501 block_t *p_buf = block_Alloc( buf_size );
502 if( buf_size > 0 ) memcpy( p_buf->p_buffer, buf, buf_size );
503
504 if( p_sys->b_write_header )
505 p_buf->i_flags |= BLOCK_FLAG_HEADER;
506 #if LIBAVFORMAT_VERSION_CHECK( 57, 7, 0, 40, 100 )
507 if( !p_sys->b_header_done )
508 p_buf->i_flags |= BLOCK_FLAG_HEADER;
509 #endif
510
511 if( p_sys->b_write_keyframe )
512 {
513 p_buf->i_flags |= BLOCK_FLAG_TYPE_I;
514 p_sys->b_write_keyframe = false;
515 }
516
517 i_ret = sout_AccessOutWrite( p_mux->p_access, p_buf );
518 return i_ret ? i_ret : -1;
519 }
520
IOSeek(void * opaque,int64_t offset,int whence)521 static int64_t IOSeek( void *opaque, int64_t offset, int whence )
522 {
523 sout_mux_t *p_mux = opaque;
524
525 #ifdef AVFORMAT_DEBUG
526 msg_Dbg( p_mux, "IOSeek offset: %"PRId64", whence: %i", offset, whence );
527 #endif
528
529 switch( whence )
530 {
531 case SEEK_SET:
532 return sout_AccessOutSeek( p_mux->p_access, offset );
533 case SEEK_CUR:
534 case SEEK_END:
535 default:
536 return -1;
537 }
538 }
539