]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/mux.c
Plugins: include vlc_common.h directly instead of vlc/vlc.h
[vlc] / modules / codec / ffmpeg / mux.c
1 /*****************************************************************************
2  * mux.c: muxer using ffmpeg (libavformat).
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 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 General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, 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 /* ffmpeg header */
37 #ifdef HAVE_LIBAVFORMAT_AVFORMAT_H
38 #   include <libavformat/avformat.h>
39 #elif defined(HAVE_FFMPEG_AVFORMAT_H)
40 #   include <ffmpeg/avformat.h>
41 #endif
42
43 #include "ffmpeg.h"
44
45 //#define AVFORMAT_DEBUG 1
46
47 /* Version checking */
48 #if defined(HAVE_LIBAVFORMAT_AVFORMAT_H) || defined(HAVE_FFMPEG_AVFORMAT_H)
49
50 static const char *const ppsz_mux_options[] = {
51     "mux", NULL
52 };
53
54 /*****************************************************************************
55  * mux_sys_t: mux descriptor
56  *****************************************************************************/
57 struct sout_mux_sys_t
58 {
59     ByteIOContext   io;
60     int             io_buffer_size;
61     uint8_t        *io_buffer;
62
63     AVFormatContext *oc;
64     URLContext     url;
65     URLProtocol    prot;
66
67     bool     b_write_header;
68     bool     b_error;
69
70     int64_t        i_initial_dts;
71 };
72
73 /*****************************************************************************
74  * Local prototypes
75  *****************************************************************************/
76 static int Control  ( sout_mux_t *, int, va_list );
77 static int AddStream( sout_mux_t *, sout_input_t * );
78 static int DelStream( sout_mux_t *, sout_input_t * );
79 static int Mux      ( sout_mux_t * );
80
81 static int IOWrite( void *opaque, uint8_t *buf, int buf_size );
82 static offset_t IOSeek( void *opaque, offset_t offset, int whence );
83
84 /*****************************************************************************
85  * Open
86  *****************************************************************************/
87 int OpenMux( vlc_object_t *p_this )
88 {
89     AVOutputFormat *file_oformat;
90     sout_mux_t *p_mux = (sout_mux_t*)p_this;
91     sout_mux_sys_t *p_sys;
92     AVFormatParameters params, *ap = &params;
93     char *psz_mux;
94
95     /* Should we call it only once ? */
96     av_register_all();
97     av_log_set_callback( LibavcodecCallback );
98
99     config_ChainParse( p_mux, "ffmpeg-", ppsz_mux_options, p_mux->p_cfg );
100
101     /* Find the requested muxer */
102     psz_mux = var_GetNonEmptyString( p_mux, "ffmpeg-mux" );
103     if( psz_mux )
104     {
105         file_oformat = guess_format( psz_mux, NULL, NULL );
106     }
107     else
108     {
109         file_oformat =
110             guess_format(NULL, p_mux->p_access->psz_path, NULL);
111     }
112     if (!file_oformat)
113     {
114       msg_Err( p_mux, "unable for find a suitable output format" );
115       return VLC_EGENERIC;
116     }
117
118     /* Fill p_mux fields */
119     p_mux->pf_control   = Control;
120     p_mux->pf_addstream = AddStream;
121     p_mux->pf_delstream = DelStream;
122     p_mux->pf_mux       = Mux;
123     p_mux->p_sys = p_sys = malloc( sizeof( sout_mux_sys_t ) );
124
125     p_sys->oc = av_alloc_format_context();
126     p_sys->oc->oformat = file_oformat;
127
128     /* Create I/O wrapper */
129     p_sys->io_buffer_size = 32768;  /* FIXME */
130     p_sys->io_buffer = malloc( p_sys->io_buffer_size );
131     p_sys->url.priv_data = p_mux;
132     p_sys->url.prot = &p_sys->prot;
133     p_sys->url.prot->name = "VLC I/O wrapper";
134     p_sys->url.prot->url_open = 0;
135     p_sys->url.prot->url_read = 0;
136     p_sys->url.prot->url_write =
137                     (int (*) (URLContext *, unsigned char *, int))IOWrite;
138     p_sys->url.prot->url_seek =
139                     (offset_t (*) (URLContext *, offset_t, int))IOSeek;
140     p_sys->url.prot->url_close = 0;
141     p_sys->url.prot->next = 0;
142     init_put_byte( &p_sys->io, p_sys->io_buffer, p_sys->io_buffer_size,
143                    1, &p_sys->url, NULL, IOWrite, IOSeek );
144
145     memset( ap, 0, sizeof(*ap) );
146     if( av_set_parameters( p_sys->oc, ap ) < 0 )
147     {
148         msg_Err( p_mux, "invalid encoding parameters" );
149         av_free( p_sys->oc );
150         free( p_sys->io_buffer );
151         free( p_sys );
152         return VLC_EGENERIC;
153     }
154
155 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0)
156     p_sys->oc->pb = &p_sys->io;
157 #else
158     p_sys->oc->pb = p_sys->io;
159 #endif
160     p_sys->oc->nb_streams = 0;
161
162     p_sys->b_write_header = true;
163     p_sys->b_error = false;
164     p_sys->i_initial_dts = 0;
165
166     return VLC_SUCCESS;
167 }
168
169 /*****************************************************************************
170  * Close
171  *****************************************************************************/
172 void CloseMux( vlc_object_t *p_this )
173 {
174     sout_mux_t *p_mux = (sout_mux_t*)p_this;
175     sout_mux_sys_t *p_sys = p_mux->p_sys;
176     unsigned int i;
177
178     if( av_write_trailer( p_sys->oc ) < 0 )
179     {
180         msg_Err( p_mux, "could not write trailer" );
181     }
182
183     for( i = 0 ; i < p_sys->oc->nb_streams; i++ )
184     {
185         if( p_sys->oc->streams[i]->codec->extradata )
186             av_free( p_sys->oc->streams[i]->codec->extradata );
187         av_free( p_sys->oc->streams[i]->codec );
188         av_free( p_sys->oc->streams[i] );
189     }
190     av_free( p_sys->oc );
191
192     free( p_sys->io_buffer );
193     free( p_sys );
194 }
195
196 /*****************************************************************************
197  * AddStream
198  *****************************************************************************/
199 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
200 {
201     sout_mux_sys_t *p_sys = p_mux->p_sys;
202     AVCodecContext *codec;
203     AVStream *stream;
204     int i_codec_id, i_aspect_num, i_aspect_den;
205
206     msg_Dbg( p_mux, "adding input" );
207
208     if( !GetFfmpegCodec( p_input->p_fmt->i_codec, 0, &i_codec_id, 0 ) )
209     {
210         msg_Dbg( p_mux, "couldn't find codec for fourcc '%4.4s'",
211                  (char *)&p_input->p_fmt->i_codec );
212         return VLC_EGENERIC;
213     }
214
215     p_input->p_sys = malloc( sizeof( int ) );
216     *((int *)p_input->p_sys) = p_sys->oc->nb_streams;
217
218     stream = av_new_stream( p_sys->oc, p_sys->oc->nb_streams);
219     if( !stream )
220     {
221         free( p_input->p_sys );
222         return VLC_EGENERIC;
223     }
224     codec = stream->codec;
225
226     /* This is used by LibavcodecCallback (ffmpeg.c) to print messages */
227     codec->opaque = (void*)p_mux;
228
229     switch( p_input->p_fmt->i_cat )
230     {
231     case AUDIO_ES:
232         codec->codec_type = CODEC_TYPE_AUDIO;
233         codec->channels = p_input->p_fmt->audio.i_channels;
234         codec->sample_rate = p_input->p_fmt->audio.i_rate;
235         codec->time_base = (AVRational){1, codec->sample_rate};
236         break;
237
238     case VIDEO_ES:
239         if( !p_input->p_fmt->video.i_frame_rate ||
240             !p_input->p_fmt->video.i_frame_rate_base )
241         {
242             msg_Warn( p_mux, "Missing frame rate, assuming 25fps" );
243             p_input->p_fmt->video.i_frame_rate = 25;
244             p_input->p_fmt->video.i_frame_rate_base = 1;
245         }
246         codec->codec_type = CODEC_TYPE_VIDEO;
247         codec->width = p_input->p_fmt->video.i_width;
248         codec->height = p_input->p_fmt->video.i_height;
249         av_reduce( &i_aspect_num, &i_aspect_den,
250                    p_input->p_fmt->video.i_aspect,
251                    VOUT_ASPECT_FACTOR, 1 << 30 /* something big */ );
252         av_reduce( &codec->sample_aspect_ratio.num,
253                    &codec->sample_aspect_ratio.den,
254                    i_aspect_num * (int64_t)codec->height,
255                    i_aspect_den * (int64_t)codec->width, 1 << 30 );
256         codec->time_base.den = p_input->p_fmt->video.i_frame_rate;
257         codec->time_base.num = p_input->p_fmt->video.i_frame_rate_base;
258         break;
259
260     default:
261         msg_Warn( p_mux, "Unhandled ES category" );
262     }
263
264     codec->bit_rate = p_input->p_fmt->i_bitrate;
265 #if LIBAVFORMAT_VERSION_INT >= ((51<<16)+(8<<8)+0)
266     codec->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id );
267     if( !codec->codec_tag && i_codec_id == CODEC_ID_MP2 )
268     {
269         i_codec_id = CODEC_ID_MP3;
270         codec->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id );
271     }
272 #else
273 #   warning "WARNING!!!!!!!"
274 #   warning "Using libavformat muxing with versions older than 51.8.0 (r7593) might produce broken files."
275     /* This is a hack */
276     if( i_codec_id == CODEC_ID_MP2 )
277         i_codec_id = CODEC_ID_MP3;
278     codec->codec_tag = p_input->p_fmt->i_codec;
279 #endif
280     codec->codec_id = i_codec_id;
281
282     if( p_input->p_fmt->i_extra )
283     {
284         codec->extradata_size = p_input->p_fmt->i_extra;
285         codec->extradata = av_malloc( p_input->p_fmt->i_extra );
286         memcpy( codec->extradata, p_input->p_fmt->p_extra,
287                 p_input->p_fmt->i_extra );
288     }
289
290     return VLC_SUCCESS;
291 }
292
293 /*****************************************************************************
294  * DelStream
295  *****************************************************************************/
296 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
297 {
298     msg_Dbg( p_mux, "removing input" );
299     free( p_input->p_sys );
300     return VLC_SUCCESS;
301 }
302
303 /*
304  * TODO  move this function to src/stream_output.c (used by nearly all muxers)
305  */
306 static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
307 {
308     mtime_t i_dts;
309     int     i_stream, i;
310
311     for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
312     {
313         block_fifo_t  *p_fifo;
314
315         p_fifo = p_mux->pp_inputs[i]->p_fifo;
316
317         /* We don't really need to have anything in the SPU fifo */
318         if( p_mux->pp_inputs[i]->p_fmt->i_cat == SPU_ES &&
319             block_FifoCount( p_fifo ) == 0 ) continue;
320
321         if( block_FifoCount( p_fifo ) )
322         {
323             block_t *p_buf;
324
325             p_buf = block_FifoShow( p_fifo );
326             if( i_stream < 0 || p_buf->i_dts < i_dts )
327             {
328                 i_dts = p_buf->i_dts;
329                 i_stream = i;
330             }
331         }
332         else return -1;
333
334     }
335     if( pi_stream ) *pi_stream = i_stream;
336     if( pi_dts ) *pi_dts = i_dts;
337     if( !p_mux->p_sys->i_initial_dts ) p_mux->p_sys->i_initial_dts = i_dts;
338     return i_stream;
339 }
340
341 static int MuxBlock( sout_mux_t *p_mux, sout_input_t *p_input )
342 {
343     sout_mux_sys_t *p_sys = p_mux->p_sys;
344     block_t *p_data = block_FifoGet( p_input->p_fifo );
345     int i_stream = *((int *)p_input->p_sys);
346     AVStream *p_stream = p_sys->oc->streams[i_stream];
347     AVPacket pkt;
348
349     memset( &pkt, 0, sizeof(AVPacket) );
350
351     av_init_packet(&pkt);
352     pkt.data = p_data->p_buffer;
353     pkt.size = p_data->i_buffer;
354     pkt.stream_index = i_stream;
355
356     if( p_data->i_flags & BLOCK_FLAG_TYPE_I ) pkt.flags |= PKT_FLAG_KEY;
357
358     /* avformat expects pts/dts which start from 0 */
359     p_data->i_dts -= p_mux->p_sys->i_initial_dts;
360     p_data->i_pts -= p_mux->p_sys->i_initial_dts;
361
362     if( p_data->i_pts > 0 )
363         pkt.pts = p_data->i_pts * p_stream->time_base.den /
364             INT64_C(1000000) / p_stream->time_base.num;
365     if( p_data->i_dts > 0 )
366         pkt.dts = p_data->i_dts * p_stream->time_base.den /
367             INT64_C(1000000) / p_stream->time_base.num;
368
369     /* this is another hack to prevent libavformat from triggering the "non monotone timestamps" check in avformat/utils.c */
370     p_stream->cur_dts = ( p_data->i_dts * p_stream->time_base.den /
371             INT64_C(1000000) / p_stream->time_base.num ) - 1;
372
373     if( av_write_frame( p_sys->oc, &pkt ) < 0 )
374     {
375         msg_Err( p_mux, "could not write frame (pts: %"PRId64", dts: %"PRId64") "
376                  "(pkt pts: %"PRId64", dts: %"PRId64")",
377                  p_data->i_pts, p_data->i_dts, pkt.pts, pkt.dts );
378         block_Release( p_data );
379         return VLC_EGENERIC;
380     }
381
382     block_Release( p_data );
383     return VLC_SUCCESS;
384 }
385
386 /*****************************************************************************
387  * Mux: multiplex available data in input fifos
388  *****************************************************************************/
389 static int Mux( sout_mux_t *p_mux )
390 {
391     sout_mux_sys_t *p_sys = p_mux->p_sys;
392     int i_stream;
393
394     if( p_sys->b_error ) return VLC_EGENERIC;
395
396     if( p_sys->b_write_header )
397     {
398         msg_Dbg( p_mux, "writing header" );
399
400         if( av_write_header( p_sys->oc ) < 0 )
401         {
402             msg_Err( p_mux, "could not write header" );
403             p_sys->b_write_header = false;
404             p_sys->b_error = true;
405             return VLC_EGENERIC;
406         }
407
408 #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0)
409         put_flush_packet( p_sys->oc->pb );
410 #else
411         put_flush_packet( &p_sys->oc->pb );
412 #endif
413         p_sys->b_write_header = false;
414     }
415
416     for( ;; )
417     {
418         if( MuxGetStream( p_mux, &i_stream, 0 ) < 0 ) return VLC_SUCCESS;
419         MuxBlock( p_mux, p_mux->pp_inputs[i_stream] );
420     }
421
422     return VLC_SUCCESS;
423 }
424
425 /*****************************************************************************
426  * Control:
427  *****************************************************************************/
428 static int Control( sout_mux_t *p_mux, int i_query, va_list args )
429 {
430     bool *pb_bool;
431
432     switch( i_query )
433     {
434     case MUX_CAN_ADD_STREAM_WHILE_MUXING:
435         pb_bool = (bool*)va_arg( args, bool * );
436         *pb_bool = false;
437         return VLC_SUCCESS;
438
439     case MUX_GET_ADD_STREAM_WAIT:
440         pb_bool = (bool*)va_arg( args, bool * );
441         *pb_bool = true;
442         return VLC_SUCCESS;
443
444     case MUX_GET_MIME:
445     {
446         char **ppsz = (char**)va_arg( args, char ** );
447         *ppsz = strdup( p_mux->p_sys->oc->oformat->mime_type );
448         return VLC_SUCCESS;
449     }
450
451     default:
452         return VLC_EGENERIC;
453     }
454 }
455
456 /*****************************************************************************
457  * I/O wrappers for libavformat
458  *****************************************************************************/
459 static int IOWrite( void *opaque, uint8_t *buf, int buf_size )
460 {
461     URLContext *p_url = opaque;
462     sout_mux_t *p_mux = p_url->priv_data;
463     int i_ret;
464
465 #ifdef AVFORMAT_DEBUG
466     msg_Dbg( p_mux, "IOWrite %i bytes", buf_size );
467 #endif
468
469     block_t *p_buf = block_New( p_mux->p_sout, buf_size );
470     if( buf_size > 0 ) memcpy( p_buf->p_buffer, buf, buf_size );
471
472     if( p_mux->p_sys->b_write_header )
473         p_buf->i_flags |= BLOCK_FLAG_HEADER;
474
475     i_ret = sout_AccessOutWrite( p_mux->p_access, p_buf );
476     return i_ret ? i_ret : -1;
477 }
478
479 static offset_t IOSeek( void *opaque, offset_t offset, int whence )
480 {
481     URLContext *p_url = opaque;
482     sout_mux_t *p_mux = p_url->priv_data;
483     int64_t i_absolute;
484
485 #ifdef AVFORMAT_DEBUG
486     msg_Dbg( p_mux, "IOSeek offset: %"PRId64", whence: %i", offset, whence );
487 #endif
488
489     switch( whence )
490     {
491     case SEEK_SET:
492         i_absolute = offset;
493         break;
494     case SEEK_CUR:
495     case SEEK_END:
496     default:
497         return -1;
498     }
499
500     if( sout_AccessOutSeek( p_mux->p_access, i_absolute ) )
501     {
502         return -1;
503     }
504
505     return 0;
506 }
507
508 #endif /* HAVE_FFMPEG_AVFORMAT_H */