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