demux: smooth: use es_format_Change
[vlc.git] / modules / demux / smooth / playlist / ForgedInitSegment.cpp
blob828e1fe9b249b501d20c6eb3610970dc4196d17f
1 /*
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 *****************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include "ForgedInitSegment.hpp"
25 #include "MemoryChunk.hpp"
26 #include "../adaptive/playlist/SegmentChunk.hpp"
28 #include <vlc_common.h>
30 #include <cstdlib>
32 extern "C"
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_,
44 uint64_t timescale_,
45 uint64_t duration_) :
46 InitSegment(parent), TimescaleAble()
48 type = type_;
49 duration.Set(duration_);
50 extradata = NULL;
51 i_extradata = 0;
52 setTimescale(timescale_);
53 formatex.cbSize = 0;
54 formatex.nAvgBytesPerSec = 0;
55 formatex.nBlockAlign = 0;
56 formatex.nChannels = 0;
57 formatex.nSamplesPerSec = 0;
58 formatex.wBitsPerSample = 0;
59 formatex.wFormatTag = 0;
60 width = height = 0;
61 fourcc = 0;
62 es_type = 0;
63 track_id = 1;
66 ForgedInitSegment::~ForgedInitSegment()
68 free(extradata);
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);
75 if(data)
77 for(size_t i=0; i<*decoded_size; i++)
78 data[i] = std::strtoul(s.substr(i*2, 2).c_str(), NULL, 16);
80 return data;
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))
97 if(extradata)
99 free(extradata);
100 extradata = NULL;
101 i_extradata = 0;
103 formatex.cbSize = __MIN(i_data - sizeof(WAVEFORMATEX), formatex.cbSize);
104 extradata = (uint8_t*)malloc(formatex.cbSize);
105 if(extradata)
107 memcpy(extradata, &p_data[sizeof(WAVEFORMATEX)], formatex.cbSize);
108 i_extradata = formatex.cbSize;
111 es_type = AUDIO_ES;
115 void ForgedInitSegment::fromVideoInfoHeader(const uint8_t *, size_t)
117 // VIDEOINFOHEADER
118 es_type = VIDEO_ES;
121 void ForgedInitSegment::setWaveFormatEx(const std::string &waveformat)
123 size_t i_data;
124 uint8_t *p_data = HexDecode(waveformat, &i_data);
125 fromWaveFormatEx(p_data, i_data);
126 free(p_data);
129 void ForgedInitSegment::setCodecPrivateData(const std::string &extra)
131 if(extradata)
133 free(extradata);
134 extradata = NULL;
135 i_extradata = 0;
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)
166 width = w;
167 height = h;
170 void ForgedInitSegment::setTrackID(unsigned i)
172 track_id = i;
175 void ForgedInitSegment::setAudioTag(uint16_t i)
177 wf_tag_to_fourcc(i, &fourcc, NULL);
180 void ForgedInitSegment::setFourCC(const std::string &fcc)
182 if(fcc.size() == 4)
184 fourcc = VLC_FOURCC(fcc[0], fcc[1], fcc[2], fcc[3]);
185 switch(fourcc)
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' ):
191 es_type = VIDEO_ES;
192 break;
193 case VLC_FOURCC( 'A', 'A', 'C', 'L' ):
194 case VLC_FOURCC( 'W', 'M', 'A', 'P' ):
195 default:
196 es_type = AUDIO_ES;
197 break;
202 void ForgedInitSegment::setLanguage(const std::string &lang)
204 language = 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;
220 switch(es_type)
222 case VIDEO_ES:
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;
249 break;
251 case AUDIO_ES:
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;
267 default:
268 break;
271 if(!language.empty())
272 trackinfo.fmt.psz_language = strdup(language.c_str());
274 mp4mux_trackinfo_t *p_tracks = &trackinfo;
275 bo_t *box = NULL;
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;
285 if(box)
287 moov = box->b;
288 free(box);
291 if(!moov)
292 return 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));
297 if(box)
299 block_ChainAppend(&box->b, moov);
300 moov = block_ChainGather(box->b);
301 free(box);
304 return moov;
307 SegmentChunk* ForgedInitSegment::toChunk(size_t, BaseRepresentation *rep, AbstractConnectionManager *)
309 block_t *moov = buildMoovBox();
310 if(moov)
312 MemoryChunkSource *source = new (std::nothrow) MemoryChunkSource(moov);
313 if( source )
315 SegmentChunk *chunk = new (std::nothrow) SegmentChunk(this, source, rep);
316 if( chunk )
317 return chunk;
318 else
319 delete source;
322 return NULL;