2 * ForgedInitSegment.cpp
3 *****************************************************************************
4 * Copyright (C) 2015 - VideoLAN Authors
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
24 #include "ForgedInitSegment.hpp"
25 #include "MemoryChunk.hpp"
26 #include "../adaptive/playlist/SegmentChunk.hpp"
28 #include <vlc_common.h>
34 #include "../../mux/mp4/libmp4mux.h"
35 #include "../../demux/mp4/libmp4.h" /* majors */
38 using namespace adaptive::playlist
;
39 using namespace smooth::playlist
;
40 using namespace smooth::http
;
42 ForgedInitSegment::ForgedInitSegment(ICanonicalUrl
*parent
,
43 const std::string
&type_
,
46 InitSegment(parent
), TimescaleAble()
49 duration
.Set(duration_
);
52 setTimescale(timescale_
);
54 formatex
.nAvgBytesPerSec
= 0;
55 formatex
.nBlockAlign
= 0;
56 formatex
.nChannels
= 0;
57 formatex
.nSamplesPerSec
= 0;
58 formatex
.wBitsPerSample
= 0;
59 formatex
.wFormatTag
= 0;
66 ForgedInitSegment::~ForgedInitSegment()
71 static uint8_t *HexDecode(const std::string
&s
, size_t *decoded_size
)
73 *decoded_size
= s
.size() / 2;
74 uint8_t *data
= (uint8_t *) malloc(*decoded_size
);
77 for(size_t i
=0; i
<*decoded_size
; i
++)
78 data
[i
] = std::strtoul(s
.substr(i
*2, 2).c_str(), NULL
, 16);
83 void ForgedInitSegment::fromWaveFormatEx(const uint8_t *p_data
, size_t i_data
)
85 if(i_data
>= sizeof(WAVEFORMATEX
))
87 formatex
.wFormatTag
= GetWLE(p_data
);
88 wf_tag_to_fourcc(formatex
.wFormatTag
, &fourcc
, NULL
);
89 formatex
.nChannels
= GetWLE(&p_data
[2]);
90 formatex
.nSamplesPerSec
= GetDWLE(&p_data
[4]);
91 formatex
.nAvgBytesPerSec
= GetDWLE(&p_data
[8]);
92 formatex
.nBlockAlign
= GetWLE(&p_data
[12]);
93 formatex
.wBitsPerSample
= GetWLE(&p_data
[14]);
94 formatex
.cbSize
= GetWLE(&p_data
[16]);
95 if(i_data
> sizeof(WAVEFORMATEX
))
103 formatex
.cbSize
= __MIN(i_data
- sizeof(WAVEFORMATEX
), formatex
.cbSize
);
104 extradata
= (uint8_t*)malloc(formatex
.cbSize
);
107 memcpy(extradata
, &p_data
[sizeof(WAVEFORMATEX
)], formatex
.cbSize
);
108 i_extradata
= formatex
.cbSize
;
115 void ForgedInitSegment::fromVideoInfoHeader(const uint8_t *, size_t)
121 void ForgedInitSegment::setWaveFormatEx(const std::string
&waveformat
)
124 uint8_t *p_data
= HexDecode(waveformat
, &i_data
);
125 fromWaveFormatEx(p_data
, i_data
);
129 void ForgedInitSegment::setCodecPrivateData(const std::string
&extra
)
137 extradata
= HexDecode(extra
, &i_extradata
);
138 if(fourcc
== VLC_CODEC_WMAP
)
140 //fromWaveFormatEx(const std::string &extra);
144 void ForgedInitSegment::setChannels(uint16_t i
)
146 formatex
.nChannels
= i
;
149 void ForgedInitSegment::setPacketSize(uint16_t i
)
151 formatex
.nBlockAlign
= i
;
154 void ForgedInitSegment::setSamplingRate(uint32_t i
)
156 formatex
.nSamplesPerSec
= i
;
159 void ForgedInitSegment::setBitsPerSample(uint16_t i
)
161 formatex
.wBitsPerSample
= i
;
164 void ForgedInitSegment::setVideoSize(unsigned w
, unsigned h
)
170 void ForgedInitSegment::setTrackID(unsigned i
)
175 void ForgedInitSegment::setAudioTag(uint16_t i
)
177 wf_tag_to_fourcc(i
, &fourcc
, NULL
);
180 void ForgedInitSegment::setFourCC(const std::string
&fcc
)
184 fourcc
= VLC_FOURCC(fcc
[0], fcc
[1], fcc
[2], fcc
[3]);
187 case VLC_FOURCC( 'A', 'V', 'C', '1' ):
188 case VLC_FOURCC( 'A', 'V', 'C', 'B' ):
189 case VLC_FOURCC( 'H', '2', '6', '4' ):
190 case VLC_FOURCC( 'W', 'V', 'C', '1' ):
193 case VLC_FOURCC( 'A', 'A', 'C', 'L' ):
194 case VLC_FOURCC( 'W', 'M', 'A', 'P' ):
202 void ForgedInitSegment::setLanguage(const std::string
&lang
)
207 block_t
* ForgedInitSegment::buildMoovBox()
209 const Timescale
&trackTimescale
= inheritTimescale();
210 mp4mux_trackinfo_t trackinfo
;
211 mp4mux_trackinfo_Init(&trackinfo
,
212 0x01, /* Will always be 1st and unique track; tfhd patched on block read */
213 (uint32_t) trackTimescale
);
214 trackinfo
.i_read_duration
= duration
.Get();
215 trackinfo
.i_trex_default_length
= 1;
216 trackinfo
.i_trex_default_size
= 1;
218 es_format_Change(&trackinfo
.fmt
, es_type
, vlc_fourcc_GetCodec(es_type
, fourcc
));
219 trackinfo
.fmt
.i_original_fourcc
= fourcc
;
223 if( fourcc
== VLC_FOURCC( 'A', 'V', 'C', '1' ) ||
224 fourcc
== VLC_FOURCC( 'A', 'V', 'C', 'B' ) ||
225 fourcc
== VLC_FOURCC( 'H', '2', '6', '4' ) )
227 trackinfo
.fmt
.i_codec
= VLC_CODEC_H264
;
229 else if( fourcc
== VLC_FOURCC( 'W', 'V', 'C', '1' ) )
231 trackinfo
.fmt
.i_codec
= VLC_CODEC_VC1
;
232 // trackinfo.fmt.video.i_bits_per_pixel = 0x18; // No clue why this was set in smooth streamfilter
235 trackinfo
.fmt
.video
.i_width
= width
;
236 trackinfo
.fmt
.video
.i_height
= height
;
237 trackinfo
.fmt
.video
.i_visible_width
= width
;
238 trackinfo
.fmt
.video
.i_visible_height
= height
;
240 if(i_extradata
&& extradata
)
242 trackinfo
.fmt
.p_extra
= malloc(i_extradata
);
243 if(trackinfo
.fmt
.p_extra
)
245 memcpy(trackinfo
.fmt
.p_extra
, extradata
, i_extradata
);
246 trackinfo
.fmt
.i_extra
= i_extradata
;
252 trackinfo
.fmt
.audio
.i_channels
= formatex
.nChannels
;
253 trackinfo
.fmt
.audio
.i_rate
= formatex
.nSamplesPerSec
;
254 trackinfo
.fmt
.audio
.i_bitspersample
= formatex
.wBitsPerSample
;
255 trackinfo
.fmt
.audio
.i_blockalign
= formatex
.nBlockAlign
;
256 trackinfo
.fmt
.i_bitrate
= formatex
.nAvgBytesPerSec
* 8; // FIXME (use bitrate) ?
258 if(i_extradata
&& extradata
)
260 trackinfo
.fmt
.p_extra
= malloc(i_extradata
);
261 if(trackinfo
.fmt
.p_extra
)
263 memcpy(trackinfo
.fmt
.p_extra
, extradata
, i_extradata
);
264 trackinfo
.fmt
.i_extra
= i_extradata
;
271 if(!language
.empty())
272 trackinfo
.fmt
.psz_language
= strdup(language
.c_str());
274 mp4mux_trackinfo_t
*p_tracks
= &trackinfo
;
277 if(mp4mux_CanMux( NULL
, &trackinfo
.fmt
))
278 box
= mp4mux_GetMoovBox(NULL
, &p_tracks
, 1,
279 trackTimescale
.ToTime(duration
.Get()),
280 true, false, false, false);
282 mp4mux_trackinfo_Clear(&trackinfo
);
284 block_t
*moov
= NULL
;
294 vlc_fourcc_t extra
[] = {MAJOR_isom
, VLC_FOURCC('p','i','f','f'), VLC_FOURCC('i','s','o','2'), VLC_FOURCC('s','m','o','o')};
295 box
= mp4mux_GetFtyp(VLC_FOURCC('i','s','m','l'), 1, extra
, ARRAY_SIZE(extra
));
299 block_ChainAppend(&box
->b
, moov
);
300 moov
= block_ChainGather(box
->b
);
307 SegmentChunk
* ForgedInitSegment::toChunk(size_t, BaseRepresentation
*rep
, AbstractConnectionManager
*)
309 block_t
*moov
= buildMoovBox();
312 MemoryChunkSource
*source
= new (std::nothrow
) MemoryChunkSource(moov
);
315 SegmentChunk
*chunk
= new (std::nothrow
) SegmentChunk(this, source
, rep
);