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