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