]> git.sesse.net Git - vlc/blob - modules/mux/mp4.c
mux: mp4: fix NALU size endianness
[vlc] / modules / mux / mp4.c
1 /*****************************************************************************
2  * mp4.c: mp4/mov muxer
3  *****************************************************************************
4  * Copyright (C) 2001, 2002, 2003, 2006 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_sout.h>
36 #include <vlc_block.h>
37
38 #include <vlc_bits.h>
39
40 #include <time.h>
41
42 #include <vlc_iso_lang.h>
43 #include <vlc_meta.h>
44
45 #include "../demux/mpeg/mpeg_parser_helpers.h"
46 #include "../demux/mp4/libmp4.h"
47
48 #include "assert.h"
49 /*****************************************************************************
50  * Module descriptor
51  *****************************************************************************/
52 #define FASTSTART_TEXT N_("Create \"Fast Start\" files")
53 #define FASTSTART_LONGTEXT N_(\
54     "Create \"Fast Start\" files. " \
55     "\"Fast Start\" files are optimized for downloads and allow the user " \
56     "to start previewing the file while it is downloading.")
57
58 static int  Open   (vlc_object_t *);
59 static void Close  (vlc_object_t *);
60 static int  OpenFrag   (vlc_object_t *);
61 static void CloseFrag  (vlc_object_t *);
62
63 #define SOUT_CFG_PREFIX "sout-mp4-"
64
65 vlc_module_begin ()
66     set_description(N_("MP4/MOV muxer"))
67     set_category(CAT_SOUT)
68     set_subcategory(SUBCAT_SOUT_MUX)
69     set_shortname("MP4")
70
71     add_bool(SOUT_CFG_PREFIX "faststart", true,
72               FASTSTART_TEXT, FASTSTART_LONGTEXT,
73               true)
74     set_capability("sout mux", 5)
75     add_shortcut("mp4", "mov", "3gp")
76     set_callbacks(Open, Close)
77
78 add_submodule ()
79     set_description(N_("Fragmented and streamable MP4 muxer"))
80     set_category(CAT_SOUT)
81     set_subcategory(SUBCAT_SOUT_MUX)
82     set_shortname("MP4 Frag")
83     add_shortcut("mp4frag", "mp4stream")
84     set_capability("sout mux", 0)
85     set_callbacks(OpenFrag, CloseFrag)
86
87 vlc_module_end ()
88
89 /*****************************************************************************
90  * Exported prototypes
91  *****************************************************************************/
92 static const char *const ppsz_sout_options[] = {
93     "faststart", NULL
94 };
95
96 static int Control(sout_mux_t *, int, va_list);
97 static int AddStream(sout_mux_t *, sout_input_t *);
98 static void DelStream(sout_mux_t *, sout_input_t *);
99 static int Mux      (sout_mux_t *);
100 static int MuxFrag  (sout_mux_t *);
101
102 /*****************************************************************************
103  * Local prototypes
104  *****************************************************************************/
105 typedef struct
106 {
107     uint64_t i_pos;
108     int      i_size;
109
110     mtime_t  i_pts_dts;
111     mtime_t  i_length;
112     unsigned int i_flags;
113 } mp4_entry_t;
114
115 typedef struct mp4_fragentry_t mp4_fragentry_t;
116
117 struct mp4_fragentry_t
118 {
119     block_t  *p_block;
120     uint32_t  i_run;
121     mp4_fragentry_t *p_next;
122 };
123
124 typedef struct mp4_fragindex_t
125 {
126     uint64_t i_moofoffset;
127     mtime_t  i_time;
128     uint8_t  i_traf;
129     uint8_t  i_trun;
130     uint32_t i_sample;
131 } mp4_fragindex_t;
132
133 typedef struct mp4_fragqueue_t
134 {
135     mp4_fragentry_t *p_first;
136     mp4_fragentry_t *p_last;
137 } mp4_fragqueue_t;
138
139 typedef struct
140 {
141     es_format_t   fmt;
142     unsigned int  i_track_id;
143
144     /* index */
145     unsigned int i_entry_count;
146     unsigned int i_entry_max;
147     mp4_entry_t  *entry;
148     int64_t      i_length_neg;
149
150     /* stats */
151     int64_t      i_dts_start; /* applies to current segment only */
152     int64_t      i_read_duration;
153     uint32_t     i_timescale;
154     mtime_t      i_starttime; /* the really first packet */
155     bool         b_hasbframes;
156
157     /* XXX: needed for other codecs too, see lavf */
158     block_t      *a52_frame;
159
160     /* for later stco fix-up (fast start files) */
161     uint64_t i_stco_pos;
162     bool b_stco64;
163
164     /* for spu */
165     int64_t i_last_dts; /* applies to current segment only */
166     int64_t i_last_length;
167
168     /*** mp4frag ***/
169     bool         b_hasiframes;
170     uint32_t     i_trex_length;
171     uint32_t     i_trex_size;
172     uint32_t     i_tfhd_flags;
173
174     uint32_t         i_current_run;
175     mp4_fragentry_t *p_held_entry;
176     mp4_fragqueue_t  read;
177     mp4_fragqueue_t  towrite;
178     mtime_t          i_last_iframe_time;
179     mtime_t          i_written_duration;
180     mp4_fragindex_t *p_indexentries;
181     uint32_t         i_indexentriesmax;
182     uint32_t         i_indexentries;
183 } mp4_stream_t;
184
185 struct sout_mux_sys_t
186 {
187     bool b_mov;
188     bool b_3gp;
189     bool b_64_ext;
190     bool b_fast_start;
191
192     uint64_t i_mdat_pos;
193     uint64_t i_pos;
194     mtime_t  i_read_duration;
195
196     unsigned int   i_nb_streams;
197     mp4_stream_t **pp_streams;
198
199     /* mp4frag */
200     bool           b_fragmented;
201     bool           b_header_sent;
202     mtime_t        i_written_duration;
203     uint32_t       i_mfhd_sequence;
204 };
205
206 static bo_t *box_new     (const char *fcc);
207 static bo_t *box_full_new(const char *fcc, uint8_t v, uint32_t f);
208 static void  box_fix     (bo_t *box);
209 static void  box_gather  (bo_t *box, bo_t *box2);
210
211 static void box_send(sout_mux_t *p_mux,  bo_t *box);
212
213 static bo_t *GetMoovBox(sout_mux_t *p_mux);
214
215 static block_t *ConvertSUBT(block_t *);
216 static block_t *ConvertFromAnnexB(block_t *);
217
218 static const char avc1_start_code[4] = { 0, 0, 0, 1 };
219
220 /*****************************************************************************
221  * Open:
222  *****************************************************************************/
223 static int Open(vlc_object_t *p_this)
224 {
225     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
226     sout_mux_sys_t  *p_sys;
227     bo_t            *box;
228
229     msg_Dbg(p_mux, "Mp4 muxer opened");
230     config_ChainParse(p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg);
231
232     p_mux->pf_control   = Control;
233     p_mux->pf_addstream = AddStream;
234     p_mux->pf_delstream = DelStream;
235     p_mux->pf_mux       = Mux;
236     p_mux->p_sys        = p_sys = malloc(sizeof(sout_mux_sys_t));
237     if (!p_sys)
238         return VLC_ENOMEM;
239     p_sys->i_pos        = 0;
240     p_sys->i_nb_streams = 0;
241     p_sys->pp_streams   = NULL;
242     p_sys->i_mdat_pos   = 0;
243     p_sys->b_mov        = p_mux->psz_mux && !strcmp(p_mux->psz_mux, "mov");
244     p_sys->b_3gp        = p_mux->psz_mux && !strcmp(p_mux->psz_mux, "3gp");
245     p_sys->i_read_duration   = 0;
246     p_sys->b_fragmented = false;
247
248     if (!p_sys->b_mov) {
249         /* Now add ftyp header */
250         box = box_new("ftyp");
251         if (p_sys->b_3gp)
252             bo_add_fourcc(box, "3gp6");
253         else
254             bo_add_fourcc(box, "isom");
255         bo_add_32be  (box, 0);
256         if (p_sys->b_3gp)
257             bo_add_fourcc(box, "3gp4");
258         else
259             bo_add_fourcc(box, "mp41");
260         bo_add_fourcc(box, "avc1");
261         box_fix(box);
262
263         p_sys->i_pos += box->len;
264         p_sys->i_mdat_pos = p_sys->i_pos;
265
266         box_send(p_mux, box);
267     }
268
269     /* FIXME FIXME
270      * Quicktime actually doesn't like the 64 bits extensions !!! */
271     p_sys->b_64_ext = false;
272
273     /* Now add mdat header */
274     box = box_new("mdat");
275     bo_add_64be  (box, 0); // enough to store an extended size
276
277     p_sys->i_pos += box->len;
278
279     box_send(p_mux, box);
280
281     return VLC_SUCCESS;
282 }
283
284 /*****************************************************************************
285  * Close:
286  *****************************************************************************/
287 static void Close(vlc_object_t *p_this)
288 {
289     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
290     sout_mux_sys_t  *p_sys = p_mux->p_sys;
291
292     msg_Dbg(p_mux, "Close");
293
294     /* Update mdat size */
295     bo_t bo;
296     bo_init(&bo, 1024);
297     if (p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32)) {
298         /* Extended size */
299         bo_add_32be  (&bo, 1);
300         bo_add_fourcc(&bo, "mdat");
301         bo_add_64be  (&bo, p_sys->i_pos - p_sys->i_mdat_pos);
302     } else {
303         bo_add_32be  (&bo, 8);
304         bo_add_fourcc(&bo, "wide");
305         bo_add_32be  (&bo, p_sys->i_pos - p_sys->i_mdat_pos - 8);
306         bo_add_fourcc(&bo, "mdat");
307     }
308
309     bo.b->i_buffer = bo.len;
310     sout_AccessOutSeek(p_mux->p_access, p_sys->i_mdat_pos);
311     sout_AccessOutWrite(p_mux->p_access, bo.b);
312
313     /* Create MOOV header */
314     uint64_t i_moov_pos = p_sys->i_pos;
315     bo_t *moov = GetMoovBox(p_mux);
316
317     /* Check we need to create "fast start" files */
318     p_sys->b_fast_start = var_GetBool(p_this, SOUT_CFG_PREFIX "faststart");
319     while (p_sys->b_fast_start) {
320         /* Move data to the end of the file so we can fit the moov header
321          * at the start */
322         int64_t i_size = p_sys->i_pos - p_sys->i_mdat_pos;
323         int i_moov_size = moov->len;
324
325         while (i_size > 0) {
326             int64_t i_chunk = __MIN(32768, i_size);
327             block_t *p_buf = block_Alloc(i_chunk);
328             sout_AccessOutSeek(p_mux->p_access,
329                                 p_sys->i_mdat_pos + i_size - i_chunk);
330             if (sout_AccessOutRead(p_mux->p_access, p_buf) < i_chunk) {
331                 msg_Warn(p_this, "read() not supported by access output, "
332                           "won't create a fast start file");
333                 p_sys->b_fast_start = false;
334                 block_Release(p_buf);
335                 break;
336             }
337             sout_AccessOutSeek(p_mux->p_access, p_sys->i_mdat_pos + i_size +
338                                 i_moov_size - i_chunk);
339             sout_AccessOutWrite(p_mux->p_access, p_buf);
340             i_size -= i_chunk;
341         }
342
343         if (!p_sys->b_fast_start)
344             break;
345
346         /* Fix-up samples to chunks table in MOOV header */
347         for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
348             mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
349
350             moov->len = p_stream->i_stco_pos;
351             for (unsigned i = 0; i < p_stream->i_entry_count; ) {
352                 mp4_entry_t *entry = p_stream->entry;
353                 if (p_stream->b_stco64)
354                     bo_add_64be(moov, entry[i].i_pos + i_moov_size);
355                 else
356                     bo_add_32be(moov, entry[i].i_pos + i_moov_size);
357
358                 for (; i < p_stream->i_entry_count; i++)
359                     if (i >= p_stream->i_entry_count - 1 ||
360                         entry[i].i_pos + entry[i].i_size != entry[i+1].i_pos) {
361                         i++;
362                         break;
363                     }
364             }
365         }
366
367         moov->len = i_moov_size;
368         i_moov_pos = p_sys->i_mdat_pos;
369         p_sys->b_fast_start = false;
370     }
371
372     /* Write MOOV header */
373     sout_AccessOutSeek(p_mux->p_access, i_moov_pos);
374     box_send(p_mux, moov);
375
376     /* Clean-up */
377     for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
378         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
379
380         es_format_Clean(&p_stream->fmt);
381         if (p_stream->a52_frame)
382             block_Release(p_stream->a52_frame);
383         free(p_stream->entry);
384         free(p_stream);
385     }
386     if (p_sys->i_nb_streams)
387         free(p_sys->pp_streams);
388     free(p_sys);
389 }
390
391 /*****************************************************************************
392  * Control:
393  *****************************************************************************/
394 static int Control(sout_mux_t *p_mux, int i_query, va_list args)
395 {
396     VLC_UNUSED(p_mux);
397     bool *pb_bool;
398
399     switch(i_query)
400     {
401     case MUX_CAN_ADD_STREAM_WHILE_MUXING:
402         pb_bool = (bool*)va_arg(args, bool *);
403         *pb_bool = false;
404         return VLC_SUCCESS;
405
406     case MUX_GET_ADD_STREAM_WAIT:
407         pb_bool = (bool*)va_arg(args, bool *);
408         *pb_bool = true;
409         return VLC_SUCCESS;
410
411     case MUX_GET_MIME:   /* Not needed, as not streamable */
412     default:
413         return VLC_EGENERIC;
414     }
415 }
416
417 /*****************************************************************************
418  * AddStream:
419  *****************************************************************************/
420 static int AddStream(sout_mux_t *p_mux, sout_input_t *p_input)
421 {
422     sout_mux_sys_t  *p_sys = p_mux->p_sys;
423     mp4_stream_t    *p_stream;
424
425     switch(p_input->p_fmt->i_codec)
426     {
427     case VLC_CODEC_A52:
428     case VLC_CODEC_EAC3:
429     case VLC_CODEC_MP4A:
430     case VLC_CODEC_MP4V:
431     case VLC_CODEC_MPGA:
432     case VLC_CODEC_MPGV:
433     case VLC_CODEC_MP2V:
434     case VLC_CODEC_MP1V:
435     case VLC_CODEC_MJPG:
436     case VLC_CODEC_MJPGB:
437     case VLC_CODEC_SVQ1:
438     case VLC_CODEC_SVQ3:
439     case VLC_CODEC_H263:
440     case VLC_CODEC_H264:
441     case VLC_CODEC_HEVC:
442     case VLC_CODEC_AMR_NB:
443     case VLC_CODEC_AMR_WB:
444     case VLC_CODEC_YV12:
445     case VLC_CODEC_YUYV:
446         break;
447     case VLC_CODEC_SUBT:
448         msg_Warn(p_mux, "subtitle track added like in .mov (even when creating .mp4)");
449         break;
450     default:
451         msg_Err(p_mux, "unsupported codec %4.4s in mp4",
452                  (char*)&p_input->p_fmt->i_codec);
453         return VLC_EGENERIC;
454     }
455
456     p_stream = malloc(sizeof(mp4_stream_t));
457     if (!p_stream)
458         return VLC_ENOMEM;
459     es_format_Copy(&p_stream->fmt, p_input->p_fmt);
460     p_stream->i_track_id    = p_sys->i_nb_streams + 1;
461     p_stream->i_length_neg  = 0;
462     p_stream->i_entry_count = 0;
463     p_stream->i_entry_max   = 1000;
464     p_stream->entry         =
465         calloc(p_stream->i_entry_max, sizeof(mp4_entry_t));
466     p_stream->i_dts_start   = 0;
467     p_stream->i_read_duration    = 0;
468     p_stream->a52_frame = NULL;
469     switch( p_stream->fmt.i_cat )
470     {
471     case AUDIO_ES:
472         if(!p_stream->fmt.audio.i_rate)
473         {
474             msg_Warn( p_mux, "no audio rate given for stream %d, assuming 48KHz",
475                       p_sys->i_nb_streams );
476             p_stream->fmt.audio.i_rate = 48000;
477         }
478         p_stream->i_timescale = p_stream->fmt.audio.i_rate;
479         break;
480     case VIDEO_ES:
481         if( !p_stream->fmt.video.i_frame_rate ||
482             !p_stream->fmt.video.i_frame_rate_base )
483         {
484             msg_Warn( p_mux, "Missing frame rate for stream %d, assuming 25fps",
485                       p_sys->i_nb_streams );
486             p_stream->fmt.video.i_frame_rate = 25;
487             p_stream->fmt.video.i_frame_rate_base = 1;
488         }
489         p_stream->i_timescale = p_stream->fmt.video.i_frame_rate * 1000 /
490                                 p_stream->fmt.video.i_frame_rate_base;
491         break;
492     default:
493         p_stream->i_timescale = CLOCK_FREQ;
494         break;
495     }
496
497     p_stream->i_starttime   = p_sys->i_read_duration;
498     p_stream->b_hasbframes  = false;
499
500     p_stream->i_last_dts    = 0;
501     p_stream->i_last_length = 0;
502
503     p_stream->b_hasiframes  = false;
504     p_stream->i_trex_length = 0;
505     p_stream->i_trex_size   = 0;
506
507     p_stream->i_current_run = 0;
508     p_stream->read.p_first  = NULL;
509     p_stream->read.p_last   = NULL;
510     p_stream->towrite.p_first = NULL;
511     p_stream->towrite.p_last  = NULL;
512     p_stream->p_held_entry    = NULL;
513     p_stream->i_last_iframe_time = 0;
514     p_stream->i_written_duration = 0;
515     p_stream->p_indexentries     = NULL;
516     p_stream->i_indexentriesmax  = 0;
517     p_stream->i_indexentries     = 0;
518
519     p_input->p_sys          = p_stream;
520
521     msg_Dbg(p_mux, "adding input");
522
523     TAB_APPEND(p_sys->i_nb_streams, p_sys->pp_streams, p_stream);
524     return VLC_SUCCESS;
525 }
526
527 /*****************************************************************************
528  * DelStream:
529  *****************************************************************************/
530 static void DelStream(sout_mux_t *p_mux, sout_input_t *p_input)
531 {
532     VLC_UNUSED(p_input);
533     msg_Dbg(p_mux, "removing input");
534 }
535
536 /*****************************************************************************
537  * Mux:
538  *****************************************************************************/
539 static int Mux(sout_mux_t *p_mux)
540 {
541     sout_mux_sys_t *p_sys = p_mux->p_sys;
542
543     for (;;) {
544         int i_stream = sout_MuxGetStream(p_mux, 2, NULL);
545         if (i_stream < 0)
546             return(VLC_SUCCESS);
547
548         sout_input_t *p_input  = p_mux->pp_inputs[i_stream];
549         mp4_stream_t *p_stream = (mp4_stream_t*)p_input->p_sys;
550
551         block_t *p_data;
552         do {
553             p_data = block_FifoGet(p_input->p_fifo);
554             if (p_stream->fmt.i_codec == VLC_CODEC_H264 ||
555                 p_stream->fmt.i_codec == VLC_CODEC_HEVC)
556                 p_data = ConvertFromAnnexB(p_data);
557             else if (p_stream->fmt.i_codec == VLC_CODEC_SUBT)
558                 p_data = ConvertSUBT(p_data);
559             else if (p_stream->fmt.i_codec == VLC_CODEC_A52 ||
560                      p_stream->fmt.i_codec == VLC_CODEC_EAC3) {
561                 if (p_stream->a52_frame == NULL && p_data->i_buffer >= 8)
562                     p_stream->a52_frame = block_Duplicate(p_data);
563             }
564         } while (!p_data);
565
566         /* Reset reference dts in case of discontinuity (ex: gather sout) */
567         if ( p_stream->i_entry_count == 0 || p_data->i_flags & BLOCK_FLAG_DISCONTINUITY )
568         {
569             p_stream->i_dts_start = p_data->i_dts;
570             p_stream->i_last_dts = p_data->i_dts;
571             p_stream->i_length_neg = 0;
572         }
573
574         if (p_stream->fmt.i_cat != SPU_ES) {
575             /* Fix length of the sample */
576             if (block_FifoCount(p_input->p_fifo) > 0) {
577                 block_t *p_next = block_FifoShow(p_input->p_fifo);
578                 if ( p_next->i_flags & BLOCK_FLAG_DISCONTINUITY )
579                 { /* we have no way to know real length except by decoding */
580                     if ( p_stream->fmt.i_cat == VIDEO_ES )
581                     {
582                         p_data->i_length = CLOCK_FREQ *
583                                            p_stream->fmt.video.i_frame_rate_base /
584                                            p_stream->fmt.video.i_frame_rate;
585                         msg_Dbg( p_mux, "video track %u fixup to %"PRId64" for sample %u",
586                                  p_stream->i_track_id, p_data->i_length, p_stream->i_entry_count );
587                     }
588                     else if ( p_stream->fmt.i_cat == AUDIO_ES &&
589                               p_stream->fmt.audio.i_rate &&
590                               p_data->i_nb_samples )
591                     {
592                         p_data->i_length = CLOCK_FREQ * p_data->i_nb_samples /
593                                            p_stream->fmt.audio.i_rate;
594                         msg_Dbg( p_mux, "audio track %u fixup to %"PRId64" for sample %u",
595                                  p_stream->i_track_id, p_data->i_length, p_stream->i_entry_count );
596                     }
597                     else if ( p_data->i_length <= 0 )
598                     {
599                         msg_Warn( p_mux, "unknown length for track %u sample %u",
600                                   p_stream->i_track_id, p_stream->i_entry_count );
601                         p_data->i_length = 1;
602                     }
603                 }
604                 else
605                 {
606                     int64_t i_diff  = p_next->i_dts - p_data->i_dts;
607                     if (i_diff < CLOCK_FREQ) /* protection */
608                         p_data->i_length = i_diff;
609                 }
610             }
611             if (p_data->i_length <= 0) {
612                 msg_Warn(p_mux, "i_length <= 0");
613                 p_stream->i_length_neg += p_data->i_length - 1;
614                 p_data->i_length = 1;
615             } else if (p_stream->i_length_neg < 0) {
616                 int64_t i_recover = __MIN(p_data->i_length / 4, - p_stream->i_length_neg);
617
618                 p_data->i_length -= i_recover;
619                 p_stream->i_length_neg += i_recover;
620             }
621         }
622
623         if (p_stream->fmt.i_cat == SPU_ES && p_stream->i_entry_count > 0) {
624             int64_t i_length = p_data->i_dts - p_stream->i_last_dts;
625
626             if (i_length <= 0) /* FIXME handle this broken case */
627                 i_length = 1;
628
629             /* Fix last entry */
630             if (p_stream->entry[p_stream->i_entry_count-1].i_length <= 0)
631                 p_stream->entry[p_stream->i_entry_count-1].i_length = i_length;
632         }
633
634         /* add index entry */
635         mp4_entry_t *e = &p_stream->entry[p_stream->i_entry_count];
636         e->i_pos    = p_sys->i_pos;
637         e->i_size   = p_data->i_buffer;
638
639         if ( p_data->i_dts > VLC_TS_INVALID && p_data->i_pts > p_data->i_dts )
640         {
641             e->i_pts_dts = p_data->i_pts - p_data->i_dts;
642             if ( !p_stream->b_hasbframes )
643                 p_stream->b_hasbframes = true;
644         }
645         else e->i_pts_dts = 0;
646
647         e->i_length = p_data->i_length;
648         e->i_flags  = p_data->i_flags;
649
650         p_stream->i_entry_count++;
651         /* XXX: -1 to always have 2 entry for easy adding of empty SPU */
652         if (p_stream->i_entry_count >= p_stream->i_entry_max - 1) {
653             p_stream->i_entry_max += 1000;
654             p_stream->entry = xrealloc(p_stream->entry,
655                          p_stream->i_entry_max * sizeof(mp4_entry_t));
656         }
657
658         /* update */
659         p_stream->i_read_duration += __MAX( 0, p_data->i_length );
660         p_stream->i_last_length = p_data->i_length;
661         p_sys->i_pos += p_data->i_buffer;
662
663         /* Save the DTS for SPU */
664         p_stream->i_last_dts = p_data->i_dts;
665
666         /* write data */
667         sout_AccessOutWrite(p_mux->p_access, p_data);
668
669         /* close subtitle with empty frame */
670         if (p_stream->fmt.i_cat == SPU_ES) {
671             int64_t i_length = p_stream->entry[p_stream->i_entry_count-1].i_length;
672
673             if ( i_length != 0 && (p_data = block_Alloc(3)) ) {
674                 /* TODO */
675                 msg_Dbg(p_mux, "writing an empty sub") ;
676
677                 /* Append a idx entry */
678                 mp4_entry_t *e = &p_stream->entry[p_stream->i_entry_count];
679                 e->i_pos    = p_sys->i_pos;
680                 e->i_size   = 3;
681                 e->i_pts_dts= 0;
682                 e->i_length = 0;
683                 e->i_flags  = 0;
684
685                 /* XXX: No need to grow the entry here */
686                 p_stream->i_entry_count++;
687
688                 /* Fix last dts */
689                 p_stream->i_last_dts += i_length;
690
691                 /* Write a " " */
692                 p_data->i_dts = p_stream->i_last_dts;
693                 p_data->i_dts = p_data->i_pts;
694                 p_data->p_buffer[0] = 0;
695                 p_data->p_buffer[1] = 1;
696                 p_data->p_buffer[2] = ' ';
697
698                 p_sys->i_pos += p_data->i_buffer;
699
700                 sout_AccessOutWrite(p_mux->p_access, p_data);
701             }
702
703             /* Fix duration = current segment starttime + duration within */
704             p_stream->i_read_duration = p_stream->i_starttime + ( p_stream->i_last_dts - p_stream->i_dts_start );
705         }
706     }
707
708     /* Update the global segment/media duration */
709     for ( unsigned int i=0; i<p_sys->i_nb_streams; i++ )
710     {
711         if ( p_sys->pp_streams[i]->i_read_duration > p_sys->i_read_duration )
712             p_sys->i_read_duration = p_sys->pp_streams[i]->i_read_duration;
713     }
714
715     return(VLC_SUCCESS);
716 }
717
718 /*****************************************************************************
719  *
720  *****************************************************************************/
721 static block_t *ConvertSUBT(block_t *p_block)
722 {
723     p_block = block_Realloc(p_block, 2, p_block->i_buffer);
724     if( !p_block )
725         return NULL;
726     /* No trailling '\0' */
727     if (p_block->i_buffer > 2 && p_block->p_buffer[p_block->i_buffer-1] == '\0')
728         p_block->i_buffer--;
729
730     p_block->p_buffer[0] = ((p_block->i_buffer - 2) >> 8)&0xff;
731     p_block->p_buffer[1] = ((p_block->i_buffer - 2)     )&0xff;
732
733     return p_block;
734 }
735
736 static block_t *ConvertFromAnnexB(block_t *p_block)
737 {
738     uint8_t *last = p_block->p_buffer;  /* Assume it starts with 0x00000001 */
739     uint8_t *dat  = &p_block->p_buffer[4];
740     uint8_t *end = &p_block->p_buffer[p_block->i_buffer];
741
742
743     /* Replace the 4 bytes start code with 4 bytes size,
744      * FIXME are all startcodes 4 bytes ? (I don't think :(*/
745     while (dat < end) {
746         while (dat < end - 4) {
747             if (!memcmp(dat, avc1_start_code, 4))
748                 break;
749             dat++;
750         }
751         if (dat >= end - 4)
752             dat = end;
753
754         /* Fix size */
755         int i_size = dat - &last[4];
756         SetDWBE((uint32_t*) last, i_size);
757
758         /* Skip blocks with SPS/PPS */
759         //if ((last[4]&0x1f) == 7 || (last[4]&0x1f) == 8)
760         //    ; // FIXME Find a way to skip dat without frelling everything
761         last = dat;
762         dat += 4;
763     }
764     return p_block;
765 }
766
767 static bo_t *GetESDS(mp4_stream_t *p_stream)
768 {
769     bo_t *esds;
770     int64_t i_bitrate_avg = 0;
771     int64_t i_bitrate_max = 0;
772
773     /* Compute avg/max bitrate */
774     for (unsigned i = 0; i < p_stream->i_entry_count; i++) {
775         i_bitrate_avg += p_stream->entry[i].i_size;
776         if (p_stream->entry[i].i_length > 0) {
777             int64_t i_bitrate = INT64_C(8000000) * p_stream->entry[i].i_size / p_stream->entry[i].i_length;
778             if (i_bitrate > i_bitrate_max)
779                 i_bitrate_max = i_bitrate;
780         }
781     }
782
783     if (p_stream->i_read_duration > 0)
784         i_bitrate_avg = INT64_C(8000000) * i_bitrate_avg / p_stream->i_read_duration;
785     else
786         i_bitrate_avg = 0;
787     if (i_bitrate_max <= 1)
788         i_bitrate_max = 0x7fffffff;
789
790     /* */
791     int i_decoder_specific_info_size = (p_stream->fmt.i_extra > 0) ? 5 + p_stream->fmt.i_extra : 0;
792
793     esds = box_full_new("esds", 0, 0);
794
795     /* ES_Descr */
796     bo_add_mp4_tag_descr(esds, 0x03, 3 + 5 + 13 + i_decoder_specific_info_size + 5 + 1);
797     bo_add_16be(esds, p_stream->i_track_id);
798     bo_add_8   (esds, 0x1f);      // flags=0|streamPriority=0x1f
799
800     /* DecoderConfigDescr */
801     bo_add_mp4_tag_descr(esds, 0x04, 13 + i_decoder_specific_info_size);
802
803     int  i_object_type_indication;
804     switch(p_stream->fmt.i_codec)
805     {
806     case VLC_CODEC_MP4V:
807         i_object_type_indication = 0x20;
808         break;
809     case VLC_CODEC_MP2V:
810         /* MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
811         i_object_type_indication = 0x65;
812         break;
813     case VLC_CODEC_MP1V:
814         /* MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
815         i_object_type_indication = 0x6b;
816         break;
817     case VLC_CODEC_MP4A:
818         /* FIXME for mpeg2-aac == 0x66->0x68 */
819         i_object_type_indication = 0x40;
820         break;
821     case VLC_CODEC_MPGA:
822         i_object_type_indication =
823             p_stream->fmt.audio.i_rate < 32000 ? 0x69 : 0x6b;
824         break;
825     default:
826         i_object_type_indication = 0x00;
827         break;
828     }
829     int i_stream_type = p_stream->fmt.i_cat == VIDEO_ES ? 0x04 : 0x05;
830
831     bo_add_8   (esds, i_object_type_indication);
832     bo_add_8   (esds, (i_stream_type << 2) | 1);
833     bo_add_24be(esds, 1024 * 1024);       // bufferSizeDB
834     bo_add_32be(esds, i_bitrate_max);     // maxBitrate
835     bo_add_32be(esds, i_bitrate_avg);     // avgBitrate
836
837     if (p_stream->fmt.i_extra > 0) {
838         /* DecoderSpecificInfo */
839         bo_add_mp4_tag_descr(esds, 0x05, p_stream->fmt.i_extra);
840
841         for (int i = 0; i < p_stream->fmt.i_extra; i++)
842             bo_add_8(esds, ((uint8_t*)p_stream->fmt.p_extra)[i]);
843     }
844
845     /* SL_Descr mandatory */
846     bo_add_mp4_tag_descr(esds, 0x06, 1);
847     bo_add_8    (esds, 0x02);  // sl_predefined
848
849     return esds;
850 }
851
852 static bo_t *GetWaveTag(mp4_stream_t *p_stream)
853 {
854     bo_t *wave;
855     bo_t *box;
856
857     wave = box_new("wave");
858
859     box = box_new("frma");
860     bo_add_fourcc(box, "mp4a");
861     box_gather(wave, box);
862
863     box = box_new("mp4a");
864     bo_add_32be(box, 0);
865     box_gather(wave, box);
866
867     box = GetESDS(p_stream);
868     box_gather(wave, box);
869
870     box = box_new("srcq");
871     bo_add_32be(box, 0x40);
872     box_gather(wave, box);
873
874     /* wazza ? */
875     bo_add_32be(wave, 8); /* new empty box */
876     bo_add_32be(wave, 0); /* box label */
877
878     return wave;
879 }
880
881 static bo_t *GetDec3Tag(mp4_stream_t *p_stream)
882 {
883     if (!p_stream->a52_frame)
884         return NULL;
885
886     bs_t s;
887     bs_init(&s, p_stream->a52_frame->p_buffer, sizeof(p_stream->a52_frame->i_buffer));
888     bs_skip(&s, 16); // syncword
889
890     uint8_t fscod, bsid, bsmod, acmod, lfeon, strmtyp;
891
892     bsmod = 0;
893
894     strmtyp = bs_read(&s, 2);
895
896     if (strmtyp & 0x1) // dependant or reserved stream
897         return NULL;
898
899     if (bs_read(&s, 3) != 0x0) // substreamid: we don't support more than 1 stream
900         return NULL;
901
902     int numblkscod;
903     bs_skip(&s, 11); // frmsizecod
904     fscod = bs_read(&s, 2);
905     if (fscod == 0x03) {
906         bs_skip(&s, 2); // fscod2
907         numblkscod = 3;
908     } else {
909         numblkscod = bs_read(&s, 2);
910     }
911
912     acmod = bs_read(&s, 3);
913     lfeon = bs_read1(&s);
914
915     bsid = bs_read(&s, 5);
916
917     bs_skip(&s, 5); // dialnorm
918     if (bs_read1(&s)) // compre
919         bs_skip(&s, 5); // compr
920
921     if (acmod == 0) {
922         bs_skip(&s, 5); // dialnorm2
923         if (bs_read1(&s)) // compr2e
924             bs_skip(&s, 8); // compr2
925     }
926
927     if (strmtyp == 0x1) // dependant stream XXX: unsupported
928         if (bs_read1(&s)) // chanmape
929             bs_skip(&s, 16); // chanmap
930
931     /* we have to skip mixing info to read bsmod */
932     if (bs_read1(&s)) { // mixmdate
933         if (acmod > 0x2) // 2+ channels
934             bs_skip(&s, 2); // dmixmod
935         if ((acmod & 0x1) && (acmod > 0x2)) // 3 front channels
936             bs_skip(&s, 3 + 3); // ltrtcmixlev + lorocmixlev
937         if (acmod & 0x4) // surround channel
938             bs_skip(&s, 3 + 3); // ltrsurmixlev + lorosurmixlev
939         if (lfeon)
940             if (bs_read1(&s))
941                 bs_skip(&s, 5); // lfemixlevcod
942         if (strmtyp == 0) { // independant stream
943             if (bs_read1(&s)) // pgmscle
944                 bs_skip(&s, 6); // pgmscl
945             if (acmod == 0x0) // dual mono
946                 if (bs_read1(&s)) // pgmscl2e
947                     bs_skip(&s, 6); // pgmscl2
948             if (bs_read1(&s)) // extpgmscle
949                 bs_skip(&s, 6); // extpgmscl
950             uint8_t mixdef = bs_read(&s, 2);
951             if (mixdef == 0x1)
952                 bs_skip(&s, 5);
953             else if (mixdef == 0x2)
954                 bs_skip(&s, 12);
955             else if (mixdef == 0x3) {
956                 uint8_t mixdeflen = bs_read(&s, 5);
957                 bs_skip(&s, 8 * (mixdeflen + 2));
958             }
959             if (acmod < 0x2) { // mono or dual mono
960                 if (bs_read1(&s)) // paninfoe
961                     bs_skip(&s, 14); // paninfo
962                 if (acmod == 0) // dual mono
963                     if (bs_read1(&s)) // paninfo2e
964                         bs_skip(&s, 14); // paninfo2
965             }
966             if (bs_read1(&s)) { // frmmixcfginfoe
967                 static const int blocks[4] = { 1, 2, 3, 6 };
968                 int number_of_blocks = blocks[numblkscod];
969                 if (number_of_blocks == 1)
970                     bs_skip(&s, 5); // blkmixcfginfo[0]
971                 else for (int i = 0; i < number_of_blocks; i++)
972                     if (bs_read1(&s)) // blkmixcfginfoe
973                         bs_skip(&s, 5); // blkmixcfginfo[i]
974             }
975         }
976     }
977
978     if (bs_read1(&s)) // infomdate
979         bsmod = bs_read(&s, 3);
980
981     uint8_t mp4_eac3_header[5];
982     bs_init(&s, mp4_eac3_header, sizeof(mp4_eac3_header));
983
984     int data_rate = p_stream->fmt.i_bitrate / 1000;
985     bs_write(&s, 13, data_rate);
986     bs_write(&s, 3, 0); // num_ind_sub - 1
987     bs_write(&s, 2, fscod);
988     bs_write(&s, 5, bsid);
989     bs_write(&s, 5, bsmod);
990     bs_write(&s, 3, acmod);
991     bs_write(&s, 1, lfeon);
992     bs_write(&s, 3, 0); // reserved
993     bs_write(&s, 4, 0); // num_dep_sub
994     bs_write(&s, 1, 0); // reserved
995
996     bo_t *dec3 = box_new("dec3");
997
998     bo_add_mem(dec3, sizeof(mp4_eac3_header), mp4_eac3_header);
999
1000     return dec3;
1001 }
1002
1003 static bo_t *GetDac3Tag(mp4_stream_t *p_stream)
1004 {
1005     if (!p_stream->a52_frame)
1006         return NULL;
1007
1008     bo_t *dac3 = box_new("dac3");
1009
1010     bs_t s;
1011     bs_init(&s, p_stream->a52_frame->p_buffer, sizeof(p_stream->a52_frame->i_buffer));
1012
1013     uint8_t fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
1014
1015     bs_skip(&s, 16 + 16); // syncword + crc
1016
1017     fscod = bs_read(&s, 2);
1018     frmsizecod = bs_read(&s, 6);
1019     bsid = bs_read(&s, 5);
1020     bsmod = bs_read(&s, 3);
1021     acmod = bs_read(&s, 3);
1022     if (acmod == 2)
1023         bs_skip(&s, 2); // dsurmod
1024     else {
1025         if ((acmod & 1) && acmod != 1)
1026             bs_skip(&s, 2); // cmixlev
1027         if (acmod & 4)
1028             bs_skip(&s, 2); // surmixlev
1029     }
1030
1031     lfeon = bs_read1(&s);
1032
1033     uint8_t mp4_a52_header[3];
1034     bs_init(&s, mp4_a52_header, sizeof(mp4_a52_header));
1035
1036     bs_write(&s, 2, fscod);
1037     bs_write(&s, 5, bsid);
1038     bs_write(&s, 3, bsmod);
1039     bs_write(&s, 3, acmod);
1040     bs_write(&s, 1, lfeon);
1041     bs_write(&s, 5, frmsizecod >> 1); // bit_rate_code
1042     bs_write(&s, 5, 0); // reserved
1043
1044     bo_add_mem(dac3, sizeof(mp4_a52_header), mp4_a52_header);
1045
1046     return dac3;
1047 }
1048
1049 static bo_t *GetDamrTag(mp4_stream_t *p_stream)
1050 {
1051     bo_t *damr;
1052
1053     damr = box_new("damr");
1054
1055     bo_add_fourcc(damr, "REFC");
1056     bo_add_8(damr, 0);
1057
1058     if (p_stream->fmt.i_codec == VLC_CODEC_AMR_NB)
1059         bo_add_16be(damr, 0x81ff); /* Mode set (all modes for AMR_NB) */
1060     else
1061         bo_add_16be(damr, 0x83ff); /* Mode set (all modes for AMR_WB) */
1062     bo_add_16be(damr, 0x1); /* Mode change period (no restriction) */
1063
1064     return damr;
1065 }
1066
1067 static bo_t *GetD263Tag(void)
1068 {
1069     bo_t *d263;
1070
1071     d263 = box_new("d263");
1072
1073     bo_add_fourcc(d263, "VLC ");
1074     bo_add_16be(d263, 0xa);
1075     bo_add_8(d263, 0);
1076
1077     return d263;
1078 }
1079
1080 static void hevcParseVPS(uint8_t * p_buffer, size_t i_buffer, uint8_t *general,
1081                          uint8_t * numTemporalLayer, bool * temporalIdNested)
1082 {
1083     const size_t i_decoded_nal_size = 512;
1084     uint8_t p_dec_nal[i_decoded_nal_size];
1085     size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer:i_decoded_nal_size;
1086     nal_decode(p_buffer, p_dec_nal, i_size);
1087
1088     /* first two bytes are the NAL header, 3rd and 4th are:
1089         vps_video_parameter_set_id(4)
1090         vps_reserved_3_2bis(2)
1091         vps_max_layers_minus1(6)
1092         vps_max_sub_layers_minus1(3)
1093         vps_temporal_id_nesting_flags
1094     */
1095     *numTemporalLayer =  ((p_dec_nal[3] & 0x0E) >> 1) + 1;
1096     *temporalIdNested = (bool)(p_dec_nal[3] & 0x01);
1097
1098     /* 5th & 6th are reserved 0xffff */
1099     /* copy the first 12 bytes of profile tier */
1100     memcpy(general, &p_dec_nal[6], 12);
1101 }
1102
1103 static void hevcParseSPS(uint8_t * p_buffer, size_t i_buffer, uint8_t * chroma_idc,
1104                          uint8_t *bit_depth_luma_minus8, uint8_t *bit_depth_chroma_minus8)
1105 {
1106     const size_t i_decoded_nal_size = 512;
1107     uint8_t p_dec_nal[i_decoded_nal_size];
1108     size_t i_size = (i_buffer < i_decoded_nal_size)?i_buffer-2:i_decoded_nal_size;
1109     nal_decode(p_buffer+2, p_dec_nal, i_size);
1110     bs_t bs;
1111     bs_init(&bs, p_dec_nal, i_size);
1112
1113     /* skip vps id */
1114     bs_skip(&bs, 4);
1115     uint32_t sps_max_sublayer_minus1 = bs_read(&bs, 3);
1116
1117     /* skip nesting flag */
1118     bs_skip(&bs, 1);
1119
1120     hevc_skip_profile_tiers_level(&bs, sps_max_sublayer_minus1);
1121
1122     /* skip sps id */
1123     (void) bs_read_ue( &bs );
1124
1125     *chroma_idc = bs_read_ue(&bs);
1126     if (*chroma_idc == 3)
1127         bs_skip(&bs, 1);
1128
1129     /* skip width and heigh */
1130     (void) bs_read_ue( &bs );
1131     (void) bs_read_ue( &bs );
1132
1133     uint32_t conformance_window_flag = bs_read1(&bs);
1134     if (conformance_window_flag) {
1135         /* skip offsets*/
1136         (void) bs_read_ue(&bs);
1137         (void) bs_read_ue(&bs);
1138         (void) bs_read_ue(&bs);
1139         (void) bs_read_ue(&bs);
1140     }
1141     *bit_depth_luma_minus8 = bs_read_ue(&bs);
1142     *bit_depth_chroma_minus8 = bs_read_ue(&bs);
1143 }
1144
1145 static bo_t *GetHvcCTag(mp4_stream_t *p_stream)
1146 {
1147     /* Generate hvcC box matching iso/iec 14496-15 3rd edition */
1148     bo_t *hvcC = box_new("hvcC");
1149     if(!p_stream->fmt.i_extra)
1150         return hvcC;
1151
1152     struct nal {
1153         size_t i_buffer;
1154         uint8_t * p_buffer;
1155     };
1156
1157     /* According to the specification HEVC stream can have
1158      * 16 vps id and an "unlimited" number of sps and pps id using ue(v) id*/
1159     struct nal p_vps[16], *p_sps = NULL, *p_pps = NULL, *p_sei = NULL,
1160                *p_nal = NULL;
1161     size_t i_vps = 0, i_sps = 0, i_pps = 0, i_sei = 0;
1162     uint8_t i_num_arrays = 0;
1163
1164     uint8_t * p_buffer = p_stream->fmt.p_extra;
1165     size_t i_buffer = p_stream->fmt.i_extra;
1166
1167     uint8_t general_configuration[12] = {0};
1168     uint8_t i_numTemporalLayer = 0;
1169     uint8_t i_chroma_idc = 1;
1170     uint8_t i_bit_depth_luma_minus8 = 0;
1171     uint8_t i_bit_depth_chroma_minus8 = 0;
1172     bool b_temporalIdNested = false;
1173
1174     uint32_t cmp = 0xFFFFFFFF;
1175     while (i_buffer) {
1176         /* look for start code 0X0000001 */
1177         while (i_buffer) {
1178             cmp = (cmp << 8) | *p_buffer;
1179             if((cmp ^ UINT32_C(0x100)) <= UINT32_C(0xFF))
1180                 break;
1181             p_buffer++;
1182             i_buffer--;
1183         }
1184         if (p_nal)
1185             p_nal->i_buffer = p_buffer - p_nal->p_buffer - ((i_buffer)?3:0);
1186
1187         switch (*p_buffer & 0x72) {
1188             /* VPS */
1189         case 0x40:
1190             p_nal = &p_vps[i_vps++];
1191             p_nal->p_buffer = p_buffer;
1192             /* Only keep the general profile from the first VPS
1193              * if there are several (this shouldn't happen so soon) */
1194             if (i_vps == 1) {
1195                 hevcParseVPS(p_buffer, i_buffer, general_configuration,
1196                              &i_numTemporalLayer, &b_temporalIdNested);
1197                 i_num_arrays++;
1198             }
1199             break;
1200             /* SPS */
1201         case 0x42: {
1202             struct nal * p_tmp =  realloc(p_sps, sizeof(struct nal) * (i_sps + 1));
1203             if (!p_tmp)
1204                 break;
1205             p_sps = p_tmp;
1206             p_nal = &p_sps[i_sps++];
1207             p_nal->p_buffer = p_buffer;
1208             if (i_sps == 1 && i_buffer > 15) {
1209                 /* Get Chroma_idc and bitdepths */
1210                 hevcParseSPS(p_buffer, i_buffer, &i_chroma_idc,
1211                              &i_bit_depth_luma_minus8, &i_bit_depth_chroma_minus8);
1212                 i_num_arrays++;
1213             }
1214             break;
1215             }
1216         /* PPS */
1217         case 0x44: {
1218             struct nal * p_tmp =  realloc(p_pps, sizeof(struct nal) * (i_pps + 1));
1219             if (!p_tmp)
1220                 break;
1221             p_pps = p_tmp;
1222             p_nal = &p_pps[i_pps++];
1223             p_nal->p_buffer = p_buffer;
1224             if (i_pps == 1)
1225                 i_num_arrays++;
1226             break;
1227             }
1228         /* SEI */
1229         case 0x4E:
1230         case 0x50: {
1231             struct nal * p_tmp =  realloc(p_sei, sizeof(struct nal) * (i_sei + 1));
1232             if (!p_tmp)
1233                 break;
1234             p_sei = p_tmp;
1235             p_nal = &p_sei[i_sei++];
1236             p_nal->p_buffer = p_buffer;
1237             if(i_sei == 1)
1238                 i_num_arrays++;
1239             break;
1240         }
1241         default:
1242             p_nal = NULL;
1243             break;
1244         }
1245     }
1246     bo_add_8(hvcC, 0x01);
1247     bo_add_mem(hvcC, 12, general_configuration);
1248     /* Don't set min spatial segmentation */
1249     bo_add_16be(hvcC, 0xF000);
1250     /* Don't set parallelism type since segmentation isn't set */
1251     bo_add_8(hvcC, 0xFC);
1252     bo_add_8(hvcC, (0xFC | (i_chroma_idc & 0x03)));
1253     bo_add_8(hvcC, (0xF8 | (i_bit_depth_luma_minus8 & 0x07)));
1254     bo_add_8(hvcC, (0xF8 | (i_bit_depth_chroma_minus8 & 0x07)));
1255
1256     /* Don't set framerate */
1257     bo_add_16be(hvcC, 0x0000);
1258     /* Force NAL size of 4 bytes that replace the startcode */
1259     bo_add_8(hvcC, (((i_numTemporalLayer & 0x07) << 3) |
1260                     (b_temporalIdNested << 2) | 0x03));
1261     bo_add_8(hvcC, i_num_arrays);
1262
1263     if (i_vps)
1264     {
1265         /* Write VPS without forcing array_completeness */
1266         bo_add_8(hvcC, 32);
1267         bo_add_16be(hvcC, i_vps);
1268         for (size_t i = 0; i < i_vps; i++) {
1269             p_nal = &p_vps[i];
1270             bo_add_16be(hvcC, p_nal->i_buffer);
1271             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1272         }
1273     }
1274
1275     if (i_sps) {
1276         /* Write SPS without forcing array_completeness */
1277         bo_add_8(hvcC, 33);
1278         bo_add_16be(hvcC, i_sps);
1279         for (size_t i = 0; i < i_sps; i++) {
1280             p_nal = &p_sps[i];
1281             bo_add_16be(hvcC, p_nal->i_buffer);
1282             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1283         }
1284     }
1285
1286     if (i_pps) {
1287         /* Write PPS without forcing array_completeness */
1288         bo_add_8(hvcC, 34);
1289         bo_add_16be(hvcC, i_pps);
1290         for (size_t i = 0; i < i_pps; i++) {
1291             p_nal = &p_pps[i];
1292             bo_add_16be(hvcC, p_nal->i_buffer);
1293             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1294         }
1295     }
1296
1297     if (i_sei) {
1298         /* Write SEI without forcing array_completeness */
1299         bo_add_8(hvcC, 39);
1300         bo_add_16be(hvcC, i_sei);
1301         for (size_t i = 0; i < i_sei; i++) {
1302             p_nal = &p_sei[i];
1303             bo_add_16be(hvcC, p_nal->i_buffer);
1304             bo_add_mem(hvcC, p_nal->i_buffer, p_nal->p_buffer);
1305         }
1306     }
1307     return hvcC;
1308 }
1309
1310 static bo_t *GetAvcCTag(mp4_stream_t *p_stream)
1311 {
1312     bo_t    *avcC = NULL;
1313     uint8_t *p_sps = NULL;
1314     uint8_t *p_pps = NULL;
1315     int     i_sps_size = 0;
1316     int     i_pps_size = 0;
1317
1318     if (p_stream->fmt.i_extra > 0) {
1319         /* FIXME: take into account multiple sps/pps */
1320         uint8_t *p_buffer = p_stream->fmt.p_extra;
1321         int     i_buffer = p_stream->fmt.i_extra;
1322
1323         while (i_buffer > 3) {
1324             while (memcmp(p_buffer, &avc1_start_code[1], 3)) {
1325                  i_buffer--;
1326                  p_buffer++;
1327             }
1328             const int i_nal_type = p_buffer[3]&0x1f;
1329             int i_startcode = 0;
1330
1331             for (int i_offset = 1; i_offset+2 < i_buffer ; i_offset++)
1332                 if (!memcmp(&p_buffer[i_offset], &avc1_start_code[1], 3)) {
1333                     /* we found another startcode */
1334                     i_startcode = i_offset;
1335                     while (p_buffer[i_startcode-1] == 0 && i_startcode > 0)
1336                         i_startcode--;
1337                     break;
1338                 }
1339
1340             int i_size = i_startcode ? i_startcode : i_buffer;
1341
1342             if (i_nal_type == 7) {
1343                 p_sps = &p_buffer[3];
1344                 i_sps_size = i_size - 3;
1345             }
1346             if (i_nal_type == 8) {
1347                 p_pps = &p_buffer[3];
1348                 i_pps_size = i_size - 3;
1349             }
1350             i_buffer -= i_size;
1351             p_buffer += i_size;
1352         }
1353     }
1354
1355     /* FIXME use better value */
1356     avcC = box_new("avcC");
1357     bo_add_8(avcC, 1);      /* configuration version */
1358     bo_add_8(avcC, i_sps_size ? p_sps[1] : 77);
1359     bo_add_8(avcC, i_sps_size ? p_sps[2] : 64);
1360     bo_add_8(avcC, i_sps_size ? p_sps[3] : 30);       /* level, 5.1 */
1361     bo_add_8(avcC, 0xff);   /* 0b11111100 | lengthsize = 0x11 */
1362
1363     bo_add_8(avcC, 0xe0 | (i_sps_size > 0 ? 1 : 0));   /* 0b11100000 | sps_count */
1364     if (i_sps_size > 0) {
1365         bo_add_16be(avcC, i_sps_size);
1366         bo_add_mem(avcC, i_sps_size, p_sps);
1367     }
1368
1369     bo_add_8(avcC, (i_pps_size > 0 ? 1 : 0));   /* pps_count */
1370     if (i_pps_size > 0) {
1371         bo_add_16be(avcC, i_pps_size);
1372         bo_add_mem(avcC, i_pps_size, p_pps);
1373     }
1374
1375     return avcC;
1376 }
1377
1378 /* TODO: No idea about these values */
1379 static bo_t *GetSVQ3Tag(mp4_stream_t *p_stream)
1380 {
1381     bo_t *smi = box_new("SMI ");
1382
1383     if (p_stream->fmt.i_extra > 0x4e) {
1384         uint8_t *p_end = &((uint8_t*)p_stream->fmt.p_extra)[p_stream->fmt.i_extra];
1385         uint8_t *p     = &((uint8_t*)p_stream->fmt.p_extra)[0x46];
1386
1387         while (p + 8 < p_end) {
1388             int i_size = GetDWBE(p);
1389             if (i_size <= 1) /* FIXME handle 1 as long size */
1390                 break;
1391             if (!strncmp((const char *)&p[4], "SMI ", 4)) {
1392                 bo_add_mem(smi, p_end - p - 8, &p[8]);
1393                 return smi;
1394             }
1395             p += i_size;
1396         }
1397     }
1398
1399     /* Create a dummy one in fallback */
1400     bo_add_fourcc(smi, "SEQH");
1401     bo_add_32be(smi, 0x5);
1402     bo_add_32be(smi, 0xe2c0211d);
1403     bo_add_8(smi, 0xc0);
1404
1405     return smi;
1406 }
1407
1408 static bo_t *GetUdtaTag(sout_mux_t *p_mux)
1409 {
1410     sout_mux_sys_t *p_sys = p_mux->p_sys;
1411     bo_t *udta = box_new("udta");
1412
1413     /* Requirements */
1414     for (unsigned int i_track = 0; i_track < p_sys->i_nb_streams; i_track++) {
1415         mp4_stream_t *p_stream = p_sys->pp_streams[i_track];
1416         vlc_fourcc_t codec = p_stream->fmt.i_codec;
1417
1418         if (codec == VLC_CODEC_MP4V || codec == VLC_CODEC_MP4A) {
1419             bo_t *box = box_new("\251req");
1420             /* String length */
1421             bo_add_16be(box, sizeof("QuickTime 6.0 or greater") - 1);
1422             bo_add_16be(box, 0);
1423             bo_add_mem(box, sizeof("QuickTime 6.0 or greater") - 1,
1424                         (uint8_t *)"QuickTime 6.0 or greater");
1425             box_gather(udta, box);
1426             break;
1427         }
1428     }
1429
1430     /* Encoder */
1431     {
1432         bo_t *box = box_new("\251enc");
1433         /* String length */
1434         bo_add_16be(box, sizeof(PACKAGE_STRING " stream output") - 1);
1435         bo_add_16be(box, 0);
1436         bo_add_mem(box, sizeof(PACKAGE_STRING " stream output") - 1,
1437                     (uint8_t*)PACKAGE_STRING " stream output");
1438         box_gather(udta, box);
1439     }
1440 #if 0
1441     /* Misc atoms */
1442     vlc_meta_t *p_meta = p_mux->p_sout->p_meta;
1443     if (p_meta) {
1444 #define ADD_META_BOX(type, box_string) { \
1445         bo_t *box = NULL;  \
1446         if (vlc_meta_Get(p_meta, vlc_meta_##type)) \
1447             box = box_new("\251" box_string); \
1448         if (box) { \
1449             bo_add_16be(box, strlen(vlc_meta_Get(p_meta, vlc_meta_##type))); \
1450             bo_add_16be(box, 0); \
1451             bo_add_mem(box, strlen(vlc_meta_Get(p_meta, vlc_meta_##type)), \
1452                         (uint8_t*)(vlc_meta_Get(p_meta, vlc_meta_##type))); \
1453             box_gather(udta, box); \
1454         } }
1455
1456         ADD_META_BOX(Title, "nam");
1457         ADD_META_BOX(Artist, "ART");
1458         ADD_META_BOX(Genre, "gen");
1459         ADD_META_BOX(Copyright, "cpy");
1460         ADD_META_BOX(Description, "des");
1461         ADD_META_BOX(Date, "day");
1462         ADD_META_BOX(URL, "url");
1463 #undef ADD_META_BOX
1464     }
1465 #endif
1466     return udta;
1467 }
1468
1469 static bo_t *GetSounBox(sout_mux_t *p_mux, mp4_stream_t *p_stream)
1470 {
1471     sout_mux_sys_t *p_sys = p_mux->p_sys;
1472     bool b_descr = true;
1473     vlc_fourcc_t codec = p_stream->fmt.i_codec;
1474     char fcc[4];
1475
1476     if (codec == VLC_CODEC_MPGA) {
1477         if (p_sys->b_mov) {
1478             b_descr = false;
1479             memcpy(fcc, ".mp3", 4);
1480         } else
1481             memcpy(fcc, "mp4a", 4);
1482     } else if (codec == VLC_CODEC_A52) {
1483         memcpy(fcc, "ac-3", 4);
1484     } else if (codec == VLC_CODEC_EAC3) {
1485         memcpy(fcc, "ec-3", 4);
1486     } else
1487         vlc_fourcc_to_char(codec, fcc);
1488
1489     bo_t *soun = box_new(fcc);
1490     for (int i = 0; i < 6; i++)
1491         bo_add_8(soun, 0);        // reserved;
1492     bo_add_16be(soun, 1);         // data-reference-index
1493
1494     /* SoundDescription */
1495     if (p_sys->b_mov && codec == VLC_CODEC_MP4A)
1496         bo_add_16be(soun, 1);     // version 1;
1497     else
1498         bo_add_16be(soun, 0);     // version 0;
1499     bo_add_16be(soun, 0);         // revision level (0)
1500     bo_add_32be(soun, 0);         // vendor
1501     // channel-count
1502     bo_add_16be(soun, p_stream->fmt.audio.i_channels);
1503     // sample size
1504     bo_add_16be(soun, p_stream->fmt.audio.i_bitspersample ?
1505                  p_stream->fmt.audio.i_bitspersample : 16);
1506     bo_add_16be(soun, -2);        // compression id
1507     bo_add_16be(soun, 0);         // packet size (0)
1508     bo_add_16be(soun, p_stream->fmt.audio.i_rate); // sampleratehi
1509     bo_add_16be(soun, 0);                             // sampleratelo
1510
1511     /* Extended data for SoundDescription V1 */
1512     if (p_sys->b_mov && p_stream->fmt.i_codec == VLC_CODEC_MP4A) {
1513         /* samples per packet */
1514         bo_add_32be(soun, p_stream->fmt.audio.i_frame_length);
1515         bo_add_32be(soun, 1536); /* bytes per packet */
1516         bo_add_32be(soun, 2);    /* bytes per frame */
1517         /* bytes per sample */
1518         bo_add_32be(soun, 2 /*p_stream->fmt.audio.i_bitspersample/8 */);
1519     }
1520
1521     /* Add an ES Descriptor */
1522     if (b_descr) {
1523         bo_t *box;
1524
1525         if (p_sys->b_mov && codec == VLC_CODEC_MP4A)
1526             box = GetWaveTag(p_stream);
1527         else if (codec == VLC_CODEC_AMR_NB)
1528             box = GetDamrTag(p_stream);
1529         else if (codec == VLC_CODEC_A52)
1530             box = GetDac3Tag(p_stream);
1531         else if (codec == VLC_CODEC_EAC3)
1532             box = GetDec3Tag(p_stream);
1533         else
1534             box = GetESDS(p_stream);
1535
1536         if (box)
1537             box_gather(soun, box);
1538     }
1539
1540     return soun;
1541 }
1542
1543 static bo_t *GetVideBox(mp4_stream_t *p_stream)
1544 {
1545     char fcc[4];
1546
1547     switch(p_stream->fmt.i_codec)
1548     {
1549     case VLC_CODEC_MP4V:
1550     case VLC_CODEC_MPGV: memcpy(fcc, "mp4v", 4); break;
1551     case VLC_CODEC_MJPG: memcpy(fcc, "mjpa", 4); break;
1552     case VLC_CODEC_SVQ1: memcpy(fcc, "SVQ1", 4); break;
1553     case VLC_CODEC_SVQ3: memcpy(fcc, "SVQ3", 4); break;
1554     case VLC_CODEC_H263: memcpy(fcc, "s263", 4); break;
1555     case VLC_CODEC_H264: memcpy(fcc, "avc1", 4); break;
1556     case VLC_CODEC_HEVC: memcpy(fcc, "hvc1", 4); break;
1557     case VLC_CODEC_YV12: memcpy(fcc, "yv12", 4); break;
1558     case VLC_CODEC_YUYV: memcpy(fcc, "yuy2", 4); break;
1559     default:
1560         vlc_fourcc_to_char(p_stream->fmt.i_codec, fcc);
1561         break;
1562     }
1563
1564     bo_t *vide = box_new(fcc);
1565     for (int i = 0; i < 6; i++)
1566         bo_add_8(vide, 0);        // reserved;
1567     bo_add_16be(vide, 1);         // data-reference-index
1568
1569     bo_add_16be(vide, 0);         // predefined;
1570     bo_add_16be(vide, 0);         // reserved;
1571     for (int i = 0; i < 3; i++)
1572         bo_add_32be(vide, 0);     // predefined;
1573
1574     bo_add_16be(vide, p_stream->fmt.video.i_width);  // i_width
1575     bo_add_16be(vide, p_stream->fmt.video.i_height); // i_height
1576
1577     bo_add_32be(vide, 0x00480000);                // h 72dpi
1578     bo_add_32be(vide, 0x00480000);                // v 72dpi
1579
1580     bo_add_32be(vide, 0);         // data size, always 0
1581     bo_add_16be(vide, 1);         // frames count per sample
1582
1583     // compressor name;
1584     for (int i = 0; i < 32; i++)
1585         bo_add_8(vide, 0);
1586
1587     bo_add_16be(vide, 0x18);      // depth
1588     bo_add_16be(vide, 0xffff);    // predefined
1589
1590     /* add an ES Descriptor */
1591     switch(p_stream->fmt.i_codec)
1592     {
1593     case VLC_CODEC_MP4V:
1594     case VLC_CODEC_MPGV:
1595         box_gather(vide, GetESDS(p_stream));
1596         break;
1597
1598     case VLC_CODEC_H263:
1599         box_gather(vide, GetD263Tag());
1600         break;
1601
1602     case VLC_CODEC_SVQ3:
1603         box_gather(vide, GetSVQ3Tag(p_stream));
1604         break;
1605
1606     case VLC_CODEC_H264:
1607         box_gather(vide, GetAvcCTag(p_stream));
1608         break;
1609
1610     case VLC_CODEC_HEVC:
1611         box_gather(vide, GetHvcCTag(p_stream));
1612         break;
1613     }
1614
1615     return vide;
1616 }
1617
1618 static bo_t *GetTextBox(void)
1619 {
1620     bo_t *text = box_new("text");
1621
1622     for (int i = 0; i < 6; i++)
1623         bo_add_8(text, 0);        // reserved;
1624     bo_add_16be(text, 1);         // data-reference-index
1625
1626     bo_add_32be(text, 0);         // display flags
1627     bo_add_32be(text, 0);         // justification
1628     for (int i = 0; i < 3; i++)
1629         bo_add_16be(text, 0);     // back ground color
1630
1631     bo_add_16be(text, 0);         // box text
1632     bo_add_16be(text, 0);         // box text
1633     bo_add_16be(text, 0);         // box text
1634     bo_add_16be(text, 0);         // box text
1635
1636     bo_add_64be(text, 0);         // reserved
1637     for (int i = 0; i < 3; i++)
1638         bo_add_16be(text, 0xff);  // foreground color
1639
1640     bo_add_8 (text, 9);
1641     bo_add_mem(text, 9, (uint8_t*)"Helvetica");
1642
1643     return text;
1644 }
1645
1646 static bo_t *GetStblBox(sout_mux_t *p_mux, mp4_stream_t *p_stream)
1647 {
1648     sout_mux_sys_t *p_sys = p_mux->p_sys;
1649
1650     /* sample description */
1651     bo_t *stsd = box_full_new("stsd", 0, 0);
1652     bo_add_32be(stsd, 1);
1653     if (p_stream->fmt.i_cat == AUDIO_ES)
1654         box_gather(stsd, GetSounBox(p_mux, p_stream));
1655     else if (p_stream->fmt.i_cat == VIDEO_ES)
1656         box_gather(stsd, GetVideBox(p_stream));
1657     else if (p_stream->fmt.i_cat == SPU_ES)
1658         box_gather(stsd, GetTextBox());
1659
1660     /* chunk offset table */
1661     bo_t *stco;
1662     if (p_sys->i_pos >= (((uint64_t)0x1) << 32)) {
1663         /* 64 bits version */
1664         p_stream->b_stco64 = true;
1665         stco = box_full_new("co64", 0, 0);
1666     } else {
1667         /* 32 bits version */
1668         p_stream->b_stco64 = false;
1669         stco = box_full_new("stco", 0, 0);
1670     }
1671     bo_add_32be(stco, 0);     // entry-count (fixed latter)
1672
1673     /* sample to chunk table */
1674     bo_t *stsc = box_full_new("stsc", 0, 0);
1675     bo_add_32be(stsc, 0);     // entry-count (fixed latter)
1676
1677     unsigned i_chunk = 0;
1678     unsigned i_stsc_last_val = 0, i_stsc_entries = 0;
1679     for (unsigned i = 0; i < p_stream->i_entry_count; i_chunk++) {
1680         mp4_entry_t *entry = p_stream->entry;
1681         int i_first = i;
1682
1683         if (p_stream->b_stco64)
1684             bo_add_64be(stco, entry[i].i_pos);
1685         else
1686             bo_add_32be(stco, entry[i].i_pos);
1687
1688         for (; i < p_stream->i_entry_count; i++)
1689             if (i >= p_stream->i_entry_count - 1 ||
1690                     entry[i].i_pos + entry[i].i_size != entry[i+1].i_pos) {
1691                 i++;
1692                 break;
1693             }
1694
1695         /* Add entry to the stsc table */
1696         if (i_stsc_last_val != i - i_first) {
1697             bo_add_32be(stsc, 1 + i_chunk);   // first-chunk
1698             bo_add_32be(stsc, i - i_first) ;  // samples-per-chunk
1699             bo_add_32be(stsc, 1);             // sample-descr-index
1700             i_stsc_last_val = i - i_first;
1701             i_stsc_entries++;
1702         }
1703     }
1704
1705     /* Fix stco entry count */
1706     bo_swap_32be(stco, 12, i_chunk);
1707     msg_Dbg(p_mux, "created %d chunks (stco)", i_chunk);
1708
1709     /* Fix stsc entry count */
1710     bo_swap_32be(stsc, 12, i_stsc_entries );
1711
1712     /* add stts */
1713     bo_t *stts = box_full_new("stts", 0, 0);
1714     bo_add_32be(stts, 0);     // entry-count (fixed latter)
1715
1716     unsigned i_index = 0;
1717     for (unsigned i = 0; i < p_stream->i_entry_count; i_index++) {
1718         int     i_first = i;
1719         mtime_t i_delta = p_stream->entry[i].i_length;
1720
1721         for (; i < p_stream->i_entry_count; ++i)
1722             if (i == p_stream->i_entry_count || p_stream->entry[i].i_length != i_delta)
1723                 break;
1724
1725         bo_add_32be(stts, i - i_first); // sample-count
1726         bo_add_32be(stts, (uint64_t)i_delta  * p_stream->i_timescale / CLOCK_FREQ); // sample-delta
1727     }
1728     bo_swap_32be(stts, 12, i_index);
1729
1730     /* composition time handling */
1731     bo_t *ctts = NULL;
1732     if ( p_stream->b_hasbframes && (ctts = box_full_new("ctts", 0, 0)) )
1733     {
1734         bo_add_32be(ctts, 0);
1735         i_index = 0;
1736         for (unsigned i = 0; i < p_stream->i_entry_count; i_index++)
1737         {
1738             int     i_first = i;
1739             mtime_t i_offset = p_stream->entry[i].i_pts_dts;
1740
1741             for (; i < p_stream->i_entry_count; ++i)
1742                 if (i == p_stream->i_entry_count || p_stream->entry[i].i_pts_dts != i_offset)
1743                     break;
1744
1745             bo_add_32be(ctts, i - i_first); // sample-count
1746             bo_add_32be(ctts, i_offset * p_stream->i_timescale / CLOCK_FREQ ); // sample-offset
1747         }
1748         bo_swap_32be(ctts, 12, i_index);
1749     }
1750
1751     bo_t *stsz = box_full_new("stsz", 0, 0);
1752     int i_size = 0;
1753     for (unsigned i = 0; i < p_stream->i_entry_count; i++)
1754     {
1755         if ( i == 0 )
1756             i_size = p_stream->entry[i].i_size;
1757         else if ( p_stream->entry[i].i_size != i_size )
1758         {
1759             i_size = 0;
1760             break;
1761         }
1762     }
1763     bo_add_32be(stsz, i_size);                         // sample-size
1764     bo_add_32be(stsz, p_stream->i_entry_count);       // sample-count
1765     if ( i_size == 0 ) // all samples have different size
1766     {
1767         for (unsigned i = 0; i < p_stream->i_entry_count; i++)
1768             bo_add_32be(stsz, p_stream->entry[i].i_size); // sample-size
1769     }
1770
1771     /* create stss table */
1772     bo_t *stss = NULL;
1773     i_index = 0;
1774     if ( p_stream->fmt.i_cat == VIDEO_ES || p_stream->fmt.i_cat == AUDIO_ES )
1775     {
1776         mtime_t i_interval = -1;
1777         for (unsigned i = 0; i < p_stream->i_entry_count; i++)
1778         {
1779             if ( i_interval != -1 )
1780             {
1781                 i_interval += p_stream->entry[i].i_length + p_stream->entry[i].i_pts_dts;
1782                 if ( i_interval < CLOCK_FREQ * 2 )
1783                     continue;
1784             }
1785
1786             if (p_stream->entry[i].i_flags & BLOCK_FLAG_TYPE_I) {
1787                 if (stss == NULL) {
1788                     stss = box_full_new("stss", 0, 0);
1789                     bo_add_32be(stss, 0); /* fixed later */
1790                 }
1791                 bo_add_32be(stss, 1 + i);
1792                 i_index++;
1793                 i_interval = 0;
1794             }
1795         }
1796     }
1797
1798     if (stss)
1799         bo_swap_32be(stss, 12, i_index);
1800
1801     /* Now gather all boxes into stbl */
1802     bo_t *stbl = box_new("stbl");
1803
1804     box_gather(stbl, stsd);
1805     box_gather(stbl, stts);
1806     if (stss)
1807         box_gather(stbl, stss);
1808     if (ctts)
1809         box_gather(stbl, ctts);
1810     box_gather(stbl, stsc);
1811     box_gather(stbl, stsz);
1812     p_stream->i_stco_pos = stbl->len + 16;
1813     box_gather(stbl, stco);
1814
1815     return stbl;
1816 }
1817
1818 static int64_t get_timestamp(void);
1819
1820 static void matrix_apply_rotation(es_format_t *fmt, uint32_t mvhd_matrix[9])
1821 {
1822     enum video_orientation_t orientation = ORIENT_NORMAL;
1823     if (fmt->i_cat == VIDEO_ES)
1824         orientation = fmt->video.orientation;
1825
1826 #define ATAN(a, b) do { mvhd_matrix[1] = (a) << 16; \
1827     mvhd_matrix[0] = (b) << 16; \
1828     } while(0)
1829
1830     switch (orientation) {
1831     case ORIENT_ROTATED_90:  ATAN( 1,  0); break;
1832     case ORIENT_ROTATED_180: ATAN( 0, -1); break;
1833     case ORIENT_ROTATED_270: ATAN( -1, 0); break;
1834     default:                 ATAN( 0,  1); break;
1835     }
1836
1837     mvhd_matrix[3] = mvhd_matrix[0] ? 0 : 0x10000;
1838     mvhd_matrix[4] = mvhd_matrix[1] ? 0 : 0x10000;
1839 }
1840
1841 static bo_t *GetMoovBox(sout_mux_t *p_mux)
1842 {
1843     sout_mux_sys_t *p_sys = p_mux->p_sys;
1844
1845     bo_t            *moov, *mvhd;
1846
1847     uint32_t        i_movie_timescale = 90000;
1848     int64_t         i_movie_duration  = 0;
1849     int64_t         i_timestamp = get_timestamp();
1850
1851     moov = box_new("moov");
1852
1853     /* Create general info */
1854     if ( !p_sys->b_fragmented )
1855     {
1856         for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
1857             mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
1858             i_movie_duration = __MAX(i_movie_duration, p_stream->i_read_duration);
1859         }
1860         msg_Dbg(p_mux, "movie duration %"PRId64"s", i_movie_duration / CLOCK_FREQ);
1861
1862         i_movie_duration = i_movie_duration * i_movie_timescale / CLOCK_FREQ;
1863     }
1864     else
1865         i_movie_duration = 0;
1866
1867     /* *** add /moov/mvhd *** */
1868     if (!p_sys->b_64_ext) {
1869         mvhd = box_full_new("mvhd", 0, 0);
1870         bo_add_32be(mvhd, i_timestamp);   // creation time
1871         bo_add_32be(mvhd, i_timestamp);   // modification time
1872         bo_add_32be(mvhd, i_movie_timescale);  // timescale
1873         bo_add_32be(mvhd, i_movie_duration);  // duration
1874     } else {
1875         mvhd = box_full_new("mvhd", 1, 0);
1876         bo_add_64be(mvhd, i_timestamp);   // creation time
1877         bo_add_64be(mvhd, i_timestamp);   // modification time
1878         bo_add_32be(mvhd, i_movie_timescale);  // timescale
1879         bo_add_64be(mvhd, i_movie_duration);  // duration
1880     }
1881     bo_add_32be(mvhd, 0x10000);           // rate
1882     bo_add_16be(mvhd, 0x100);             // volume
1883     bo_add_16be(mvhd, 0);                 // reserved
1884     for (int i = 0; i < 2; i++)
1885         bo_add_32be(mvhd, 0);             // reserved
1886
1887     uint32_t mvhd_matrix[9] = { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
1888
1889     for (int i = 0; i < 9; i++)
1890         bo_add_32be(mvhd, mvhd_matrix[i]);// matrix
1891     for (int i = 0; i < 6; i++)
1892         bo_add_32be(mvhd, 0);             // pre-defined
1893
1894     /* Next available track id */
1895     bo_add_32be(mvhd, p_sys->i_nb_streams + 1); // next-track-id
1896
1897     box_gather(moov, mvhd);
1898
1899     for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
1900         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
1901
1902         mtime_t i_stream_duration;
1903         if ( !p_sys->b_fragmented )
1904             i_stream_duration = p_stream->i_read_duration * i_movie_timescale / CLOCK_FREQ;
1905         else
1906             i_stream_duration = 0;
1907
1908         /* *** add /moov/trak *** */
1909         bo_t *trak = box_new("trak");
1910
1911         /* *** add /moov/trak/tkhd *** */
1912         bo_t *tkhd;
1913         if (!p_sys->b_64_ext) {
1914             if (p_sys->b_mov)
1915                 tkhd = box_full_new("tkhd", 0, 0x0f);
1916             else
1917                 tkhd = box_full_new("tkhd", 0, 1);
1918
1919             bo_add_32be(tkhd, i_timestamp);       // creation time
1920             bo_add_32be(tkhd, i_timestamp);       // modification time
1921             bo_add_32be(tkhd, p_stream->i_track_id);
1922             bo_add_32be(tkhd, 0);                     // reserved 0
1923             bo_add_32be(tkhd, i_stream_duration); // duration
1924         } else {
1925             if (p_sys->b_mov)
1926                 tkhd = box_full_new("tkhd", 1, 0x0f);
1927             else
1928                 tkhd = box_full_new("tkhd", 1, 1);
1929
1930             bo_add_64be(tkhd, i_timestamp);       // creation time
1931             bo_add_64be(tkhd, i_timestamp);       // modification time
1932             bo_add_32be(tkhd, p_stream->i_track_id);
1933             bo_add_32be(tkhd, 0);                     // reserved 0
1934             bo_add_64be(tkhd, i_stream_duration); // duration
1935         }
1936
1937         for (int i = 0; i < 2; i++)
1938             bo_add_32be(tkhd, 0);                 // reserved
1939         bo_add_16be(tkhd, 0);                     // layer
1940         bo_add_16be(tkhd, 0);                     // pre-defined
1941         // volume
1942         bo_add_16be(tkhd, p_stream->fmt.i_cat == AUDIO_ES ? 0x100 : 0);
1943         bo_add_16be(tkhd, 0);                     // reserved
1944         matrix_apply_rotation(&p_stream->fmt, mvhd_matrix);
1945         for (int i = 0; i < 9; i++)
1946             bo_add_32be(tkhd, mvhd_matrix[i]);    // matrix
1947         if (p_stream->fmt.i_cat == AUDIO_ES) {
1948             bo_add_32be(tkhd, 0);                 // width (presentation)
1949             bo_add_32be(tkhd, 0);                 // height(presentation)
1950         } else if (p_stream->fmt.i_cat == VIDEO_ES) {
1951             int i_width = p_stream->fmt.video.i_width << 16;
1952             if (p_stream->fmt.video.i_sar_num > 0 && p_stream->fmt.video.i_sar_den > 0) {
1953                 i_width = (int64_t)p_stream->fmt.video.i_sar_num *
1954                           ((int64_t)p_stream->fmt.video.i_width << 16) /
1955                           p_stream->fmt.video.i_sar_den;
1956             }
1957             // width (presentation)
1958             bo_add_32be(tkhd, i_width);
1959             // height(presentation)
1960             bo_add_32be(tkhd, p_stream->fmt.video.i_height << 16);
1961         } else {
1962             int i_width = 320 << 16;
1963             int i_height = 200;
1964             for (unsigned int i = 0; i < p_sys->i_nb_streams; i++) {
1965                 mp4_stream_t *tk = p_sys->pp_streams[i];
1966                 if (tk->fmt.i_cat == VIDEO_ES) {
1967                     if (tk->fmt.video.i_sar_num > 0 &&
1968                         tk->fmt.video.i_sar_den > 0)
1969                         i_width = (int64_t)tk->fmt.video.i_sar_num *
1970                                   ((int64_t)tk->fmt.video.i_width << 16) /
1971                                   tk->fmt.video.i_sar_den;
1972                     else
1973                         i_width = tk->fmt.video.i_width << 16;
1974                     i_height = tk->fmt.video.i_height;
1975                     break;
1976                 }
1977             }
1978             bo_add_32be(tkhd, i_width);     // width (presentation)
1979             bo_add_32be(tkhd, i_height << 16);    // height(presentation)
1980         }
1981
1982         box_gather(trak, tkhd);
1983
1984         /* *** add /moov/trak/edts and elst */
1985         if ( !p_sys->b_fragmented )
1986         {
1987             bo_t *edts = box_new("edts");
1988             bo_t *elst = box_full_new("elst", p_sys->b_64_ext ? 1 : 0, 0);
1989             if (p_stream->i_starttime > 0) {
1990                 bo_add_32be(elst, 2);
1991
1992                 if (p_sys->b_64_ext) {
1993                     bo_add_64be(elst, p_stream->i_starttime *
1994                                 i_movie_timescale / CLOCK_FREQ);
1995                     bo_add_64be(elst, -1);
1996                 } else {
1997                     bo_add_32be(elst, p_stream->i_starttime *
1998                                 i_movie_timescale / CLOCK_FREQ);
1999                     bo_add_32be(elst, -1);
2000                 }
2001                 bo_add_16be(elst, 1);
2002                 bo_add_16be(elst, 0);
2003             } else {
2004                 bo_add_32be(elst, 1);
2005             }
2006             if (p_sys->b_64_ext) {
2007                 bo_add_64be(elst, p_stream->i_read_duration *
2008                             i_movie_timescale / CLOCK_FREQ);
2009                 bo_add_64be(elst, 0);
2010             } else {
2011                 bo_add_32be(elst, p_stream->i_read_duration *
2012                             i_movie_timescale / CLOCK_FREQ);
2013                 bo_add_32be(elst, 0);
2014             }
2015             bo_add_16be(elst, 1);
2016             bo_add_16be(elst, 0);
2017
2018             box_gather(edts, elst);
2019             box_gather(trak, edts);
2020         }
2021
2022         /* *** add /moov/trak/mdia *** */
2023         bo_t *mdia = box_new("mdia");
2024
2025         /* media header */
2026         bo_t *mdhd;
2027         if (!p_sys->b_64_ext) {
2028             mdhd = box_full_new("mdhd", 0, 0);
2029             bo_add_32be(mdhd, i_timestamp);   // creation time
2030             bo_add_32be(mdhd, i_timestamp);   // modification time
2031             bo_add_32be(mdhd, p_stream->i_timescale); // timescale
2032             bo_add_32be(mdhd, i_stream_duration);  // duration
2033         } else {
2034             mdhd = box_full_new("mdhd", 1, 0);
2035             bo_add_64be(mdhd, i_timestamp);   // creation time
2036             bo_add_64be(mdhd, i_timestamp);   // modification time
2037             bo_add_32be(mdhd, p_stream->i_timescale); // timescale
2038             bo_add_64be(mdhd, i_stream_duration);  // duration
2039         }
2040
2041         if (p_stream->fmt.psz_language) {
2042             char *psz = p_stream->fmt.psz_language;
2043             const iso639_lang_t *pl = NULL;
2044             uint16_t lang = 0x0;
2045
2046             if (strlen(psz) == 2)
2047                 pl = GetLang_1(psz);
2048             else if (strlen(psz) == 3) {
2049                 pl = GetLang_2B(psz);
2050                 if (!strcmp(pl->psz_iso639_1, "??"))
2051                     pl = GetLang_2T(psz);
2052             }
2053
2054             if (pl && strcmp(pl->psz_iso639_1, "??"))
2055                 lang = ((pl->psz_iso639_2T[0] - 0x60) << 10) |
2056                        ((pl->psz_iso639_2T[1] - 0x60) <<  5) |
2057                        ((pl->psz_iso639_2T[2] - 0x60));
2058             bo_add_16be(mdhd, lang);          // language
2059         } else
2060             bo_add_16be(mdhd, 0   );          // language
2061         bo_add_16be(mdhd, 0   );              // predefined
2062         box_gather(mdia, mdhd);
2063
2064         /* handler reference */
2065         bo_t *hdlr = box_full_new("hdlr", 0, 0);
2066
2067         if (p_sys->b_mov)
2068             bo_add_fourcc(hdlr, "mhlr");         // media handler
2069         else
2070             bo_add_32be(hdlr, 0);
2071
2072         if (p_stream->fmt.i_cat == AUDIO_ES)
2073             bo_add_fourcc(hdlr, "soun");
2074         else if (p_stream->fmt.i_cat == VIDEO_ES)
2075             bo_add_fourcc(hdlr, "vide");
2076         else if (p_stream->fmt.i_cat == SPU_ES)
2077             bo_add_fourcc(hdlr, "text");
2078
2079         bo_add_32be(hdlr, 0);         // reserved
2080         bo_add_32be(hdlr, 0);         // reserved
2081         bo_add_32be(hdlr, 0);         // reserved
2082
2083         if (p_sys->b_mov)
2084             bo_add_8(hdlr, 12);   /* Pascal string for .mov */
2085
2086         if (p_stream->fmt.i_cat == AUDIO_ES)
2087             bo_add_mem(hdlr, 12, (uint8_t*)"SoundHandler");
2088         else if (p_stream->fmt.i_cat == VIDEO_ES)
2089             bo_add_mem(hdlr, 12, (uint8_t*)"VideoHandler");
2090         else
2091             bo_add_mem(hdlr, 12, (uint8_t*)"Text Handler");
2092
2093         if (!p_sys->b_mov)
2094             bo_add_8(hdlr, 0);   /* asciiz string for .mp4, yes that's BRAIN DAMAGED F**K MP4 */
2095
2096         box_gather(mdia, hdlr);
2097
2098         /* minf*/
2099         bo_t *minf = box_new("minf");
2100
2101         /* add smhd|vmhd */
2102         if (p_stream->fmt.i_cat == AUDIO_ES) {
2103             bo_t *smhd;
2104
2105             smhd = box_full_new("smhd", 0, 0);
2106             bo_add_16be(smhd, 0);     // balance
2107             bo_add_16be(smhd, 0);     // reserved
2108
2109             box_gather(minf, smhd);
2110         } else if (p_stream->fmt.i_cat == VIDEO_ES) {
2111             bo_t *vmhd;
2112
2113             vmhd = box_full_new("vmhd", 0, 1);
2114             bo_add_16be(vmhd, 0);     // graphicsmode
2115             for (int i = 0; i < 3; i++)
2116                 bo_add_16be(vmhd, 0); // opcolor
2117
2118             box_gather(minf, vmhd);
2119         } else if (p_stream->fmt.i_cat == SPU_ES) {
2120             bo_t *gmhd = box_new("gmhd");
2121             bo_t *gmin = box_full_new("gmin", 0, 1);
2122
2123             bo_add_16be(gmin, 0);     // graphicsmode
2124             for (int i = 0; i < 3; i++)
2125                 bo_add_16be(gmin, 0); // opcolor
2126             bo_add_16be(gmin, 0);     // balance
2127             bo_add_16be(gmin, 0);     // reserved
2128
2129             box_gather(gmhd, gmin);
2130
2131             box_gather(minf, gmhd);
2132         }
2133
2134         /* dinf */
2135         bo_t *dinf = box_new("dinf");
2136         bo_t *dref = box_full_new("dref", 0, 0);
2137         bo_add_32be(dref, 1);
2138         bo_t *url = box_full_new("url ", 0, 0x01);
2139         box_gather(dref, url);
2140         box_gather(dinf, dref);
2141
2142         /* append dinf to mdia */
2143         box_gather(minf, dinf);
2144
2145         /* add stbl */
2146         bo_t *stbl;
2147         if ( p_sys->b_fragmented )
2148         {
2149             uint32_t i_backup = p_stream->i_entry_count;
2150             p_stream->i_entry_count = 0;
2151             stbl = GetStblBox(p_mux, p_stream);
2152             p_stream->i_entry_count = i_backup;
2153         }
2154         else
2155             stbl = GetStblBox(p_mux, p_stream);
2156
2157         /* append stbl to minf */
2158         p_stream->i_stco_pos += minf->len;
2159         box_gather(minf, stbl);
2160
2161         /* append minf to mdia */
2162         p_stream->i_stco_pos += mdia->len;
2163         box_gather(mdia, minf);
2164
2165         /* append mdia to trak */
2166         p_stream->i_stco_pos += trak->len;
2167         box_gather(trak, mdia);
2168
2169         /* append trak to moov */
2170         p_stream->i_stco_pos += moov->len;
2171         box_gather(moov, trak);
2172     }
2173
2174     /* Add user data tags */
2175     box_gather(moov, GetUdtaTag(p_mux));
2176
2177     if ( p_sys->b_fragmented )
2178     {
2179         bo_t *mvex = box_new("mvex");
2180         for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++)
2181         {
2182             mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
2183
2184             /* Try to find some defaults */
2185             if ( p_stream->i_entry_count )
2186             {
2187                 // FIXME: find highest occurence
2188                 p_stream->i_trex_length = p_stream->entry[0].i_length;
2189                 p_stream->i_trex_size = p_stream->entry[0].i_size;
2190             }
2191
2192             /* *** add /mvex/trex *** */
2193             bo_t *trex = box_full_new("trex", 0, 0);
2194             bo_add_32be(trex, p_stream->i_track_id);
2195             bo_add_32be(trex, 1); // sample desc index
2196             bo_add_32be(trex, (uint64_t)p_stream->i_trex_length * p_stream->i_timescale / CLOCK_FREQ); // sample duration
2197             bo_add_32be(trex, p_stream->i_trex_size); // sample size
2198             bo_add_32be(trex, 0); // sample flags
2199             box_gather(mvex, trex);
2200         }
2201         box_gather(moov, mvex);
2202     }
2203
2204     box_fix(moov);
2205     return moov;
2206 }
2207
2208 /****************************************************************************/
2209
2210 static bo_t *box_new(const char *fcc)
2211 {
2212     bo_t *box = malloc(sizeof(*box));
2213     if (!box)
2214         return NULL;
2215
2216     bo_init(box, 1024);
2217
2218     bo_add_32be  (box, 0);
2219     bo_add_fourcc(box, fcc);
2220
2221     return box;
2222 }
2223
2224 static bo_t *box_full_new(const char *fcc, uint8_t v, uint32_t f)
2225 {
2226     bo_t *box = box_new(fcc);
2227     if (!box)
2228         return NULL;
2229
2230     bo_add_8     (box, v);
2231     bo_add_24be  (box, f);
2232
2233     return box;
2234 }
2235
2236 static void box_free(bo_t *box)
2237 {
2238     block_Release(box->b);
2239     free(box);
2240 }
2241
2242 static void box_fix(bo_t *box)
2243 {
2244     box->b->p_buffer[0] = box->len >> 24;
2245     box->b->p_buffer[1] = box->len >> 16;
2246     box->b->p_buffer[2] = box->len >>  8;
2247     box->b->p_buffer[3] = box->len;
2248 }
2249
2250 static void box_gather (bo_t *box, bo_t *box2)
2251 {
2252     box_fix(box2);
2253     box->b = block_Realloc(box->b, 0, box->len + box2->len);
2254     memcpy(&box->b->p_buffer[box->len], box2->b->p_buffer, box2->len);
2255     box->len += box2->len;
2256     box_free(box2);
2257 }
2258
2259 static void box_send(sout_mux_t *p_mux,  bo_t *box)
2260 {
2261     box->b->i_buffer = box->len;
2262     sout_AccessOutWrite(p_mux->p_access, box->b);
2263     free(box);
2264 }
2265
2266 static int64_t get_timestamp(void)
2267 {
2268     int64_t i_timestamp = time(NULL);
2269
2270     i_timestamp += 2082844800; // MOV/MP4 start date is 1/1/1904
2271     // 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
2272
2273     return i_timestamp;
2274 }
2275
2276 /***************************************************************************
2277     MP4 Live submodule
2278 ****************************************************************************/
2279 #define FRAGMENT_LENGTH  (CLOCK_FREQ * 3/2)
2280
2281 #define ENQUEUE_ENTRY(object, entry) \
2282     do {\
2283         if (object.p_last)\
2284             object.p_last->p_next = entry;\
2285         object.p_last = entry;\
2286         if (!object.p_first)\
2287             object.p_first = entry;\
2288     } while(0)
2289
2290 #define DEQUEUE_ENTRY(object, entry) \
2291     do {\
2292         entry = object.p_first;\
2293         if (object.p_last == entry)\
2294             object.p_last = NULL;\
2295         object.p_first = object.p_first->p_next;\
2296         entry->p_next = NULL;\
2297     } while(0)
2298
2299 /* Creates mfra/traf index entries */
2300 static void AddKeyframeEntry(mp4_stream_t *p_stream, const uint64_t i_moof_pos,
2301                              const uint8_t i_traf, const uint32_t i_sample,
2302                              const mtime_t i_time)
2303 {
2304     /* alloc or realloc */
2305     mp4_fragindex_t *p_entries = p_stream->p_indexentries;
2306     if (p_stream->i_indexentries >= p_stream->i_indexentriesmax)
2307     {
2308         p_stream->i_indexentriesmax += 256;
2309         p_entries = xrealloc(p_stream->p_indexentries,
2310                              p_stream->i_indexentriesmax * sizeof(mp4_fragindex_t));
2311         if (p_entries) /* realloc can fail */
2312             p_stream->p_indexentries = p_entries;
2313     }
2314
2315     mtime_t i_last_entry_time;
2316     if (p_stream->i_indexentries)
2317         i_last_entry_time = p_stream->p_indexentries[p_stream->i_indexentries - 1].i_time;
2318     else
2319         i_last_entry_time = 0;
2320
2321     if (p_entries && i_time - i_last_entry_time >= CLOCK_FREQ * 2)
2322     {
2323         mp4_fragindex_t *p_indexentry = &p_stream->p_indexentries[p_stream->i_indexentries];
2324         p_indexentry->i_time = i_time;
2325         p_indexentry->i_moofoffset = i_moof_pos;
2326         p_indexentry->i_sample = i_sample;
2327         p_indexentry->i_traf = i_traf;
2328         p_indexentry->i_trun = 1;
2329         p_stream->i_indexentries++;
2330     }
2331 }
2332
2333 /* Creates moof box and traf/trun information.
2334  * Single run per traf is absolutely not optimal as interleaving should be done
2335  * using runs and not limiting moof size, but creating an relative offset only
2336  * requires base_offset_is_moof and then comply to late iso brand spec which
2337  * breaks clients. */
2338 static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
2339                         mtime_t i_barrier_time, const uint64_t i_write_pos)
2340 {
2341     sout_mux_sys_t *p_sys = p_mux->p_sys;
2342
2343     bo_t            *moof, *mfhd;
2344     size_t           i_fixupoffset = 0;
2345
2346     *pi_mdat_total_size = 0;
2347
2348     moof = box_new("moof");
2349
2350     /* *** add /moof/mfhd *** */
2351
2352     mfhd = box_full_new("mfhd", 0, 0);
2353     bo_add_32be(mfhd, p_sys->i_mfhd_sequence++);   // sequence number
2354
2355     box_gather(moof, mfhd);
2356
2357     for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++)
2358     {
2359         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
2360
2361         /* *** add /moof/traf *** */
2362         bo_t *traf = box_new("traf");
2363
2364         uint32_t i_sample = 0;
2365         mtime_t i_time = p_stream->i_written_duration;
2366         bool b_allsamesize = true;
2367         bool b_allsamelength = true;
2368         if ( p_stream->read.p_first )
2369         {
2370             mp4_fragentry_t *p_entry = p_stream->read.p_first->p_next;
2371             while (p_entry && (b_allsamelength || b_allsamesize))
2372             {
2373                 /* compare against queue head */
2374                 b_allsamelength &= ( p_entry->p_block->i_length == p_stream->read.p_first->p_block->i_length );
2375                 b_allsamesize &= ( p_entry->p_block->i_buffer == p_stream->read.p_first->p_block->i_buffer );
2376                 p_entry = p_entry->p_next;
2377             }
2378         }
2379
2380         uint32_t i_tfhd_flags = 0x0;
2381         if (p_stream->read.p_first)
2382         {
2383             /* Current segment have all same duration value, different than trex's default */
2384             if (b_allsamelength &&
2385                 p_stream->read.p_first->p_block->i_length != p_stream->i_trex_length &&
2386                 p_stream->read.p_first->p_block->i_length)
2387                     i_tfhd_flags |= MP4_TFHD_DFLT_SAMPLE_DURATION;
2388
2389             /* Current segment have all same size value, different than trex's default */
2390             if (b_allsamesize &&
2391                 p_stream->read.p_first->p_block->i_buffer != p_stream->i_trex_size &&
2392                 p_stream->read.p_first->p_block->i_buffer)
2393                     i_tfhd_flags |= MP4_TFHD_DFLT_SAMPLE_SIZE;
2394         }
2395         else
2396         {
2397             /* We have no samples */
2398             i_tfhd_flags |= MP4_TFHD_DURATION_IS_EMPTY;
2399         }
2400
2401         /* *** add /moof/traf/tfhd *** */
2402         bo_t *tfhd = box_full_new("tfhd", 0, i_tfhd_flags);
2403         bo_add_32be(tfhd, p_stream->i_track_id);
2404
2405         /* set the local sample duration default */
2406         if (i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_DURATION)
2407             bo_add_32be(tfhd, p_stream->read.p_first->p_block->i_length * p_stream->i_timescale / CLOCK_FREQ);
2408
2409         /* set the local sample size default */
2410         if (i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE)
2411             bo_add_32be(tfhd, p_stream->read.p_first->p_block->i_buffer);
2412
2413         box_gather(traf, tfhd);
2414
2415         /* *** add /moof/traf/tfdt *** */
2416         bo_t *tfdt = box_full_new("tfdt", 1, 0);
2417         bo_add_64be(tfdt, p_stream->i_written_duration * p_stream->i_timescale / CLOCK_FREQ );
2418         box_gather(traf, tfdt);
2419
2420         /* *** add /moof/traf/trun *** */
2421         if (p_stream->read.p_first)
2422         {
2423             uint32_t i_trun_flags = 0x0;
2424
2425             if (p_stream->b_hasiframes && !(p_stream->read.p_first->p_block->i_flags & BLOCK_FLAG_TYPE_I))
2426                 i_trun_flags |= MP4_TRUN_FIRST_FLAGS;
2427
2428             if (!b_allsamelength ||
2429                 ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_DURATION) && p_stream->i_trex_length == 0 ))
2430                 i_trun_flags |= MP4_TRUN_SAMPLE_DURATION;
2431
2432             if (!b_allsamesize ||
2433                 ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE) && p_stream->i_trex_size == 0 ))
2434                 i_trun_flags |= MP4_TRUN_SAMPLE_SIZE;
2435
2436             if (p_stream->b_hasbframes)
2437                 i_trun_flags |= MP4_TRUN_SAMPLE_TIME_OFFSET;
2438
2439             if (i_fixupoffset == 0)
2440                 i_trun_flags |= MP4_TRUN_DATA_OFFSET;
2441
2442             bo_t *trun = box_full_new("trun", 0, i_trun_flags);
2443
2444             /* count entries */
2445             uint32_t i_entry_count = 0;
2446             mtime_t i_run_time = p_stream->i_written_duration;
2447             mp4_fragentry_t *p_entry = p_stream->read.p_first;
2448             while(p_entry)
2449             {
2450                 if ( i_barrier_time && i_run_time + p_entry->p_block->i_length > i_barrier_time )
2451                     break;
2452                 i_entry_count++;
2453                 i_run_time += p_entry->p_block->i_length;
2454                 p_entry = p_entry->p_next;
2455             }
2456             bo_add_32be(trun, i_entry_count); // sample count
2457
2458             if (i_trun_flags & MP4_TRUN_DATA_OFFSET)
2459             {
2460                 i_fixupoffset = moof->len + traf->len + trun->len;
2461                 bo_add_32be(trun, 0xdeadbeef); // data offset
2462             }
2463
2464             if (i_trun_flags & MP4_TRUN_FIRST_FLAGS)
2465                 bo_add_32be(trun, 1<<16); // flag as non keyframe
2466
2467             while(p_stream->read.p_first && i_entry_count)
2468             {
2469                 DEQUEUE_ENTRY(p_stream->read, p_entry);
2470
2471                 if (i_trun_flags & MP4_TRUN_SAMPLE_DURATION)
2472                     bo_add_32be(trun, p_entry->p_block->i_length * p_stream->i_timescale / CLOCK_FREQ); // sample duration
2473
2474                 if (i_trun_flags & MP4_TRUN_SAMPLE_SIZE)
2475                     bo_add_32be(trun, p_entry->p_block->i_buffer); // sample size
2476
2477                 if (i_trun_flags & MP4_TRUN_SAMPLE_TIME_OFFSET)
2478                 {
2479                     uint32_t i_diff = 0;
2480                     if ( p_entry->p_block->i_dts  > VLC_TS_INVALID &&
2481                          p_entry->p_block->i_pts > p_entry->p_block->i_dts )
2482                     {
2483                         i_diff = p_entry->p_block->i_pts - p_entry->p_block->i_dts;
2484                     }
2485                     bo_add_32be(trun, i_diff * p_stream->i_timescale / CLOCK_FREQ); // ctts
2486                 }
2487
2488                 *pi_mdat_total_size += p_entry->p_block->i_buffer;
2489
2490                 ENQUEUE_ENTRY(p_stream->towrite, p_entry);
2491                 i_entry_count--;
2492                 i_sample++;
2493
2494                 /* Add keyframe entry if needed */
2495                 if (p_stream->b_hasiframes && (p_entry->p_block->i_flags & BLOCK_FLAG_TYPE_I) &&
2496                     (p_stream->fmt.i_cat == VIDEO_ES || p_stream->fmt.i_cat == AUDIO_ES))
2497                 {
2498                     AddKeyframeEntry(p_stream, i_write_pos, i_trak, i_sample, i_time);
2499                 }
2500
2501                 i_time += p_entry->p_block->i_length;
2502             }
2503
2504             box_gather(traf, trun);
2505         }
2506
2507         box_gather(moof, traf);
2508     }
2509
2510     box_fix(moof);
2511
2512     /* do tfhd base data offset fixup */
2513     if (i_fixupoffset)
2514     {
2515         /* mdat will follow moof */
2516         SetDWBE(moof->b->p_buffer + i_fixupoffset, moof->len + 8);
2517     }
2518
2519     /* set iframe flag, so the streaming server always starts from moof */
2520     moof->b->i_flags |= BLOCK_FLAG_TYPE_I;
2521
2522     return moof;
2523 }
2524
2525 static void WriteFragmentMDAT(sout_mux_t *p_mux, size_t i_total_size)
2526 {
2527     sout_mux_sys_t *p_sys = p_mux->p_sys;
2528
2529     /* Now add mdat header */
2530     bo_t *mdat = box_new("mdat");
2531     /* force update of real size */
2532     mdat->b->i_buffer = mdat->len;
2533     assert(mdat->len==8);
2534     mdat->len += i_total_size;
2535     box_fix(mdat);
2536     p_sys->i_pos += mdat->b->i_buffer;
2537     /* only write header */
2538     sout_AccessOutWrite(p_mux->p_access, mdat->b);
2539     free(mdat);
2540     /* Header and its size are written and good, now write content */
2541     for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++)
2542     {
2543         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
2544
2545         while(p_stream->towrite.p_first)
2546         {
2547             mp4_fragentry_t *p_entry = p_stream->towrite.p_first;
2548             p_sys->i_pos += p_entry->p_block->i_buffer;
2549             p_stream->i_written_duration += p_entry->p_block->i_length;
2550
2551             p_entry->p_block->i_flags &= ~BLOCK_FLAG_TYPE_I; // clear flag for http stream
2552             sout_AccessOutWrite(p_mux->p_access, p_entry->p_block);
2553
2554             p_stream->towrite.p_first = p_entry->p_next;
2555             free(p_entry);
2556             if (!p_stream->towrite.p_first)
2557                 p_stream->towrite.p_last = NULL;
2558         }
2559     }
2560 }
2561
2562 static bo_t *GetMfraBox(sout_mux_t *p_mux)
2563 {
2564     sout_mux_sys_t *p_sys = (sout_mux_sys_t*) p_mux->p_sys;
2565     bo_t *mfra = NULL;
2566     for (unsigned int i = 0; i < p_sys->i_nb_streams; i++)
2567     {
2568         mp4_stream_t *p_stream = p_sys->pp_streams[i];
2569         if (p_stream->i_indexentries)
2570         {
2571             bo_t *tfra = box_full_new("tfra", 0, 0x0);
2572             if (!tfra) continue;
2573             bo_add_32be(tfra, p_stream->i_track_id);
2574             bo_add_32be(tfra, 0x3); // reserved + lengths (1,1,4)=>(0,0,3)
2575             bo_add_32be(tfra, p_stream->i_indexentries);
2576             for(uint32_t i_index=0; i_index<p_stream->i_indexentries; i_index++)
2577             {
2578                 const mp4_fragindex_t *p_indexentry = &p_stream->p_indexentries[i_index];
2579                 bo_add_32be(tfra, p_indexentry->i_time);
2580                 bo_add_32be(tfra, p_indexentry->i_moofoffset);
2581                 assert(sizeof(p_indexentry->i_traf)==1); /* guard against sys changes */
2582                 assert(sizeof(p_indexentry->i_trun)==1);
2583                 assert(sizeof(p_indexentry->i_sample)==4);
2584                 bo_add_8(tfra, p_indexentry->i_traf);
2585                 bo_add_8(tfra, p_indexentry->i_trun);
2586                 bo_add_32be(tfra, p_indexentry->i_sample);
2587             }
2588
2589             if (!mfra && !(mfra = box_new("mfra")))
2590             {
2591                 box_free(tfra);
2592                 return NULL;
2593             }
2594
2595             box_gather(mfra,tfra);
2596         }
2597     }
2598     return mfra;
2599 }
2600
2601 static void FlushHeader(sout_mux_t *p_mux)
2602 {
2603     sout_mux_sys_t *p_sys = (sout_mux_sys_t*) p_mux->p_sys;
2604
2605     /* Now add ftyp header */
2606     bo_t *ftyp = box_new("ftyp");
2607     bo_add_fourcc(ftyp, "isom");
2608     bo_add_32be  (ftyp, 0); // minor version
2609     box_fix(ftyp);
2610
2611     bo_t *moov = GetMoovBox(p_mux);
2612
2613     /* merge into a single block */
2614     box_gather(ftyp, moov);
2615
2616     /* add header flag for streaming server */
2617     ftyp->b->i_flags |= BLOCK_FLAG_HEADER;
2618     p_sys->i_pos += ftyp->len;
2619     box_send(p_mux, ftyp);
2620     p_sys->b_header_sent = true;
2621 }
2622
2623 static int OpenFrag(vlc_object_t *p_this)
2624 {
2625     sout_mux_t *p_mux = (sout_mux_t*) p_this;
2626     sout_mux_sys_t *p_sys = malloc(sizeof(sout_mux_sys_t));
2627     if (!p_sys)
2628         return VLC_ENOMEM;
2629
2630     p_mux->p_sys = (sout_mux_sys_t *) p_sys;
2631     p_mux->pf_control   = Control;
2632     p_mux->pf_addstream = AddStream;
2633     p_mux->pf_delstream = DelStream;
2634     p_mux->pf_mux       = MuxFrag;
2635
2636     /* unused */
2637     p_sys->b_mov        = false;
2638     p_sys->b_3gp        = false;
2639     p_sys->b_64_ext     = false;
2640     /* !unused */
2641
2642     p_sys->i_pos        = 0;
2643     p_sys->i_nb_streams = 0;
2644     p_sys->pp_streams   = NULL;
2645     p_sys->i_mdat_pos   = 0;
2646     p_sys->i_read_duration   = 0;
2647     p_sys->i_written_duration= 0;
2648
2649     p_sys->b_header_sent = false;
2650     p_sys->b_fragmented  = true;
2651     p_sys->i_mfhd_sequence = 1;
2652
2653     return VLC_SUCCESS;
2654 }
2655
2656 static void WriteFragments(sout_mux_t *p_mux, bool b_flush)
2657 {
2658     sout_mux_sys_t *p_sys = (sout_mux_sys_t*) p_mux->p_sys;
2659     bo_t *moof = NULL;
2660     mtime_t i_barrier_time = p_sys->i_written_duration + FRAGMENT_LENGTH;
2661     size_t i_mdat_size = 0;
2662     bool b_has_samples = false;
2663
2664     for (unsigned int i = 0; i < p_sys->i_nb_streams; i++)
2665     {
2666         const mp4_stream_t *p_stream = p_sys->pp_streams[i];
2667         if (p_stream->read.p_first)
2668         {
2669             b_has_samples = true;
2670
2671             /* set a barrier so we try to align to keyframe */
2672             if (p_stream->b_hasiframes &&
2673                     p_stream->i_last_iframe_time > p_stream->i_written_duration &&
2674                     (p_stream->fmt.i_cat == VIDEO_ES ||
2675                      p_stream->fmt.i_cat == AUDIO_ES) )
2676             {
2677                 i_barrier_time = __MIN(i_barrier_time, p_stream->i_last_iframe_time);
2678             }
2679         }
2680     }
2681
2682     if (!p_sys->b_header_sent)
2683         FlushHeader(p_mux);
2684
2685     if (b_has_samples)
2686         moof = GetMoofBox(p_mux, &i_mdat_size, (b_flush)?0:i_barrier_time, p_sys->i_pos);
2687
2688     if (moof && i_mdat_size == 0)
2689     {
2690         block_Release(moof->b);
2691         FREENULL(moof);
2692     }
2693
2694     if (moof)
2695     {
2696         msg_Dbg(p_mux, "writing moof @ %"PRId64, p_sys->i_pos);
2697         p_sys->i_pos += moof->len;
2698         assert(moof->b->i_flags & BLOCK_FLAG_TYPE_I); /* http sout */
2699         box_send(p_mux, moof);
2700         msg_Dbg(p_mux, "writing mdat @ %"PRId64, p_sys->i_pos);
2701         WriteFragmentMDAT(p_mux, i_mdat_size);
2702
2703         /* update iframe point */
2704         for (unsigned int i = 0; i < p_sys->i_nb_streams; i++)
2705         {
2706             mp4_stream_t *p_stream = p_sys->pp_streams[i];
2707             p_stream->i_last_iframe_time = 0;
2708         }
2709     }
2710 }
2711
2712 /* Do an entry length fixup using only its own info.
2713  * This is the end boundary case. */
2714 static void LengthLocalFixup(sout_mux_t *p_mux, const mp4_stream_t *p_stream, block_t *p_entrydata)
2715 {
2716     if ( p_stream->fmt.i_cat == VIDEO_ES )
2717     {
2718         p_entrydata->i_length = CLOCK_FREQ *
2719                 p_stream->fmt.video.i_frame_rate_base /
2720                 p_stream->fmt.video.i_frame_rate;
2721         msg_Dbg(p_mux, "video track %d fixup to %"PRId64" for sample %u",
2722                 p_stream->i_track_id, p_entrydata->i_length, p_stream->i_entry_count - 1);
2723     }
2724     else if (p_stream->fmt.i_cat == AUDIO_ES &&
2725              p_stream->fmt.audio.i_rate &&
2726              p_entrydata->i_nb_samples)
2727     {
2728         p_entrydata->i_length = CLOCK_FREQ * p_entrydata->i_nb_samples /
2729                 p_stream->fmt.audio.i_rate;
2730         msg_Dbg(p_mux, "audio track %d fixup to %"PRId64" for sample %u",
2731                 p_stream->i_track_id, p_entrydata->i_length, p_stream->i_entry_count - 1);
2732     }
2733     else
2734     {
2735         msg_Warn(p_mux, "unknown length for track %d sample %u",
2736                  p_stream->i_track_id, p_stream->i_entry_count - 1);
2737         p_entrydata->i_length = 1;
2738     }
2739 }
2740
2741 static void CleanupFrag(sout_mux_sys_t *p_sys)
2742 {
2743     for (unsigned int i = 0; i < p_sys->i_nb_streams; i++)
2744     {
2745         mp4_stream_t *p_stream = p_sys->pp_streams[i];
2746         if (p_stream->p_held_entry)
2747         {
2748             block_Release(p_stream->p_held_entry->p_block);
2749             free(p_stream->p_held_entry);
2750         }
2751         while(p_stream->read.p_first)
2752         {
2753             mp4_fragentry_t *p_next = p_stream->read.p_first->p_next;
2754             block_Release(p_stream->read.p_first->p_block);
2755             free(p_stream->read.p_first);
2756             p_stream->read.p_first = p_next;
2757         }
2758         while(p_stream->towrite.p_first)
2759         {
2760             mp4_fragentry_t *p_next = p_stream->towrite.p_first->p_next;
2761             block_Release(p_stream->towrite.p_first->p_block);
2762             free(p_stream->towrite.p_first);
2763             p_stream->towrite.p_first = p_next;
2764         }
2765         free(p_stream->p_indexentries);
2766     }
2767     free(p_sys);
2768 }
2769
2770 static void CloseFrag(vlc_object_t *p_this)
2771 {
2772     sout_mux_t *p_mux = (sout_mux_t *) p_this;
2773     sout_mux_sys_t *p_sys = (sout_mux_sys_t*) p_mux->p_sys;
2774
2775     /* Flush remaining entries */
2776     for (unsigned int i = 0; i < p_sys->i_nb_streams; i++)
2777     {
2778         mp4_stream_t *p_stream = p_sys->pp_streams[i];
2779         if (p_stream->p_held_entry)
2780         {
2781             if (p_stream->p_held_entry->p_block->i_length < 1)
2782                 LengthLocalFixup(p_mux, p_stream, p_stream->p_held_entry->p_block);
2783             ENQUEUE_ENTRY(p_stream->read, p_stream->p_held_entry);
2784             p_stream->p_held_entry = NULL;
2785         }
2786     }
2787
2788     /* and force creating a fragment from it */
2789     WriteFragments(p_mux, true);
2790
2791     /* Write indexes, but only for non streamed content
2792        as they refer to moof by absolute position */
2793     if (!strcmp(p_mux->psz_mux, "mp4frag"))
2794     {
2795         bo_t *mfra = GetMfraBox(p_mux);
2796         if (mfra)
2797         {
2798             bo_t *mfro = box_full_new("mfro", 0, 0x0);
2799             if (mfro)
2800             {
2801                 box_fix(mfra);
2802                 bo_add_32be(mfro, mfra->len + MP4_MFRO_BOXSIZE);
2803                 box_gather(mfra, mfro);
2804             }
2805             box_send(p_mux, mfra);
2806         }
2807     }
2808
2809     CleanupFrag(p_sys);
2810 }
2811
2812 static int MuxFrag(sout_mux_t *p_mux)
2813 {
2814     sout_mux_sys_t *p_sys = (sout_mux_sys_t*) p_mux->p_sys;
2815
2816     int i_stream = sout_MuxGetStream(p_mux, 1, NULL);
2817     if (i_stream < 0)
2818         return VLC_SUCCESS;
2819     sout_input_t *p_input  = p_mux->pp_inputs[i_stream];
2820     mp4_stream_t *p_stream = (mp4_stream_t*) p_input->p_sys;
2821     block_t *p_currentblock = block_FifoGet(p_input->p_fifo);
2822
2823     /* do block conversion */
2824     switch(p_stream->fmt.i_codec)
2825     {
2826     case VLC_CODEC_H264:
2827     case VLC_CODEC_HEVC:
2828         p_currentblock = ConvertFromAnnexB(p_currentblock);
2829         break;
2830     case VLC_CODEC_SUBT:
2831         p_currentblock = ConvertSUBT(p_currentblock);
2832         break;
2833     default:
2834         break;
2835     }
2836
2837     if( !p_currentblock )
2838         return VLC_ENOMEM;
2839
2840     /* If we have a previous entry for outgoing queue */
2841     if (p_stream->p_held_entry)
2842     {
2843         block_t *p_heldblock = p_stream->p_held_entry->p_block;
2844
2845         /* Fix previous block length from current */
2846         if (p_heldblock->i_length < 1)
2847         {
2848
2849             /* Fix using dts if not on a boundary */
2850             if ((p_currentblock->i_flags & BLOCK_FLAG_DISCONTINUITY) == 0)
2851                 p_heldblock->i_length = p_currentblock->i_dts - p_heldblock->i_dts;
2852
2853             if (p_heldblock->i_length < 1)
2854                 LengthLocalFixup(p_mux, p_stream, p_heldblock);
2855         }
2856
2857         /* enqueue */
2858         ENQUEUE_ENTRY(p_stream->read, p_stream->p_held_entry);
2859         p_stream->p_held_entry = NULL;
2860
2861         if (p_stream->b_hasiframes && (p_heldblock->i_flags & BLOCK_FLAG_TYPE_I) &&
2862             p_stream->i_read_duration - p_sys->i_written_duration < FRAGMENT_LENGTH)
2863         {
2864             /* Flag the last iframe time, we'll use it as boundary so it will start
2865                next fragment */
2866             p_stream->i_last_iframe_time = p_stream->i_read_duration;
2867         }
2868
2869         /* update buffered time */
2870         p_stream->i_read_duration += __MAX(0, p_heldblock->i_length);
2871     }
2872
2873
2874     /* set temp entry */
2875     p_stream->p_held_entry = malloc(sizeof(mp4_fragentry_t));
2876     if (unlikely(!p_stream->p_held_entry))
2877         return VLC_ENOMEM;
2878
2879     p_stream->p_held_entry->p_block  = p_currentblock;
2880     p_stream->p_held_entry->i_run    = p_stream->i_current_run;
2881     p_stream->p_held_entry->p_next   = NULL;
2882
2883     if (p_stream->fmt.i_cat == VIDEO_ES )
2884     {
2885         if (!p_stream->b_hasiframes && (p_currentblock->i_flags & BLOCK_FLAG_TYPE_I))
2886             p_stream->b_hasiframes = true;
2887
2888         if (!p_stream->b_hasbframes && p_currentblock->i_dts > VLC_TS_INVALID &&
2889             p_currentblock->i_pts > p_currentblock->i_dts)
2890             p_stream->b_hasbframes = true;
2891     }
2892
2893     /* Update the global fragment/media duration */
2894     mtime_t i_min_read_duration = p_stream->i_read_duration;
2895     mtime_t i_min_written_duration = p_stream->i_written_duration;
2896     for (unsigned int i=0; i<p_sys->i_nb_streams; i++)
2897     {
2898         const mp4_stream_t *p_s = p_sys->pp_streams[i];
2899         if (p_s->fmt.i_cat != VIDEO_ES && p_s->fmt.i_cat != AUDIO_ES)
2900             continue;
2901         if (p_s->i_read_duration < i_min_read_duration)
2902             i_min_read_duration = p_s->i_read_duration;
2903
2904         if (p_s->i_written_duration < i_min_written_duration)
2905             i_min_written_duration = p_s->i_written_duration;
2906     }
2907     p_sys->i_read_duration = i_min_read_duration;
2908     p_sys->i_written_duration = i_min_written_duration;
2909
2910     /* we have prerolled enough to know all streams, and have enough date to create a fragment */
2911     if (p_stream->read.p_first && p_sys->i_read_duration - p_sys->i_written_duration >= FRAGMENT_LENGTH)
2912         WriteFragments(p_mux, false);
2913
2914     return VLC_SUCCESS;
2915 }