1 /**********************************************************************
2 \file muxerMp4v2
3 \brief libmp4v2 muxer
4 -------------------
5
6 copyright : (C) 2011 by mean
7 email : fixounet@free.fr
8 Strongly inspired by handbrake code
9
10 ***************************************************************************/
11
12 /***************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
20
21 #include "ADM_default.h"
22 #include "fourcc.h"
23 #include "muxerMp4v2.h"
24 #include "ADM_codecType.h"
25 #include "ADM_imageFlags.h"
26 #include "ADM_vidMisc.h"
27 #if 1
28 #define aprintf(...) {}
29 #define bprintf(...) {} // ADM_info
30 #define MP4_DEBUG 0
31 #else
32 #define aprintf ADM_info
33 #define bprintf ADM_info
34 #define MP4_DEBUG MP4_DETAILS_ALL
35 #endif
36
37 #warning add audioDelay
38 #warning fix audio not starting at 0
39 /**
40 \fn addAC3
41 \brief Setup AC3 audio track
42 */
addAc3(int index,WAVHeader * header)43 bool muxerMp4v2::addAc3(int index, WAVHeader *header)
44 {
45 int fscod=0;
46 switch(header->frequency)
47 {
48 case 48000: fscod=0;break;
49 case 44100: fscod=1;break;
50 case 32000: fscod=2;break;
51 default:
52 {
53 GUI_Error_HIG("", QT_TRANSLATE_NOOP("mp4v2muxer","Invalid frequency for AC3. Only 32, 44.1 & 48 kHz"));
54 return false;
55 }
56 }
57 int bitrate;
58 static const uint16_t ac3_bitrate_tab[19] = { // From handbrake
59 32, 40, 48, 56, 64, 80, 96, 112, 128,
60 160, 192, 224, 256, 320, 384, 448, 512, 576, 640
61 };
62 int Ceil=sizeof(ac3_bitrate_tab)/sizeof(const uint16_t);
63 bitrate=-1;
64 for(int ix=0;ix<Ceil;ix++)
65 if(header->byterate==(ac3_bitrate_tab[ix]*1000)/8)
66 {
67 bitrate=ix;
68 break;
69 }
70 if(-1==bitrate)
71 {
72 GUI_Error_HIG("",QT_TRANSLATE_NOOP("mp4v2muxer","Invalid bitrate for AC3"));
73 return false;
74 }
75 int acmod,lfe=0;
76 switch(header->channels)
77 {
78 case 1: acmod=1;break;
79 case 2: acmod=2;break;
80 case 5: acmod=7;lfe=0;break;
81 #warning Check!
82 case 6: acmod=7;lfe=1;break;
83 default:
84 {
85 GUI_Error_HIG("",QT_TRANSLATE_NOOP("mp4v2muxer","Invalid number of channels for AC3"));
86 return false;
87 }
88 }
89 audioTrackIds[index]=MP4AddAC3AudioTrack(handle,
90 header->frequency,// samplingRate,
91 fscod, // fscod
92 8, // bsid,
93 0, // bsmod,
94 acmod, // acmod
95 lfe, // lfeon
96 bitrate); // bit_rate_code
97 if(MP4_INVALID_TRACK_ID==audioTrackIds[index])
98 {
99 ADM_error("Error adding audio track %i of type 0x%x\n",index,header->encoding);
100 return false;
101 }
102 aprintf("Add Track %d fq %d (AC3)\n",audioTrackIds[index],header->frequency);
103 return true;
104 }
105 /**
106 \fn initAudio
107 */
initAudio(void)108 bool muxerMp4v2::initAudio(void)
109 {
110 audioTrackIds=new MP4TrackId[nbAStreams];
111 audioPackets=new mp4v2AudioPacket[nbAStreams];
112
113 for(int i=0;i<nbAStreams;i++)
114 {
115 WAVHeader *header=aStreams[i]->getInfo();
116 ADM_audioStream*a=aStreams[i];
117 audioPackets[i].clock=new audioClock(header->frequency);
118 // Preload this track...
119 if(false==loadAndToggleAudioSlot(i))
120 {
121 audioPackets[i].eos=true;
122 continue;
123 }
124
125 switch(header->encoding)
126 {
127 case WAV_AAC:
128 {
129 uint8_t *extraData=NULL;
130 uint32_t extraDataLen=0;
131 if(!a->getExtraData(&extraDataLen,&extraData))
132 {
133 GUI_Error_HIG("AAC",QT_TRANSLATE_NOOP("mp4v2muxer","Cannot get AAC Extra data\n"));
134 return false;
135 }
136 uint32_t frameLength=a->getSamplesPerPacket();
137 audioTrackIds[i]=MP4AddAudioTrack(handle,
138 header->frequency,
139 frameLength,
140 MP4_MPEG4_AUDIO_TYPE);
141 if(MP4_INVALID_TRACK_ID==audioTrackIds[i])
142 {
143 ADM_error("Error adding audio track %i of type 0x%x\n",i,header->encoding);
144 return false;
145 }
146 aprintf("Add Track %d fq %d\n",audioTrackIds[i],header->frequency);
147 MP4SetAudioProfileLevel(handle,0x0f);
148 MP4SetTrackIntegerProperty(handle,audioTrackIds[i],"mdia.minf.stbl.stsd.mp4a.channels",
149 header->channels);
150 MP4SetTrackESConfiguration(handle,audioTrackIds[i],extraData,extraDataLen);
151 break;
152 }
153 case WAV_AC3:
154 if(false==addAc3(i, header))
155 {
156 return false;
157 }
158 break;
159 case WAV_MP2:
160 case WAV_MP3:
161 audioTrackIds[i]=MP4AddAudioTrack(handle,
162 header->frequency,
163 audioPackets[i].blocks[0].nbSamples,
164 MP4_MPEG2_AUDIO_TYPE);
165 if(MP4_INVALID_TRACK_ID==audioTrackIds[i])
166 {
167 ADM_error("Error adding audio track %i of type 0x%x\n",i,header->encoding);
168 return false;
169 }
170 aprintf("Add Track %d fq %d\n",audioTrackIds[i],header->frequency);
171 MP4SetAudioProfileLevel(handle,0x0f);
172 MP4SetTrackIntegerProperty(handle,audioTrackIds[i],"mdia.minf.stbl.stsd.mp4a.channels",
173 header->channels);
174 break;
175 default:
176 ADM_error("Cannot create audio track of type 0x%x\n",header->encoding);
177 return false;
178 }
179 if(aStreams[i]->isLanguageSet())
180 {
181 MP4SetTrackLanguage(handle,audioTrackIds[i],aStreams[i]->getLanguage().c_str());
182 ADM_info("[MP4v2] Setting language to %s \n",aStreams[i]->getLanguage().c_str());
183 }else
184 ADM_warning("[MP4v2] Language is undefined\n");
185
186 MP4SetTrackBytesProperty(handle,audioTrackIds[i],"udta.name.value",
187 (const uint8_t*)"Stereo", strlen("Stereo"));
188
189 }
190 if(nbAStreams)
191 MP4SetTrackIntegerProperty(handle, audioTrackIds[0], "tkhd.flags", 3);
192 return true;
193 }
194 /**
195 \fn loadAndToggleAudioSlot
196 */
loadAndToggleAudioSlot(int index)197 bool muxerMp4v2::loadAndToggleAudioSlot(int index)
198 {
199 ADM_audioStream *a=aStreams[index];
200 mp4v2AudioPacket *pkt=&(audioPackets[index]);
201 mp4v2AudioPacket::mp4v2AudioBlock *blk=&(pkt->blocks[pkt->nextWrite]);
202 if(!a->getPacket(blk->buffer,
203 &(blk->sizeInBytes),
204 AUDIO_BUFFER_SIZE,
205 &(blk->nbSamples),
206 &(blk->dts)))
207 {
208 ADM_warning("Cannot get audio packet for stream %d\n",index);
209 pkt->eos=true;
210 return false;
211 }
212 if(blk->dts!=ADM_NO_PTS)
213 blk->dts+=audioDelay;
214 blk->present=true;
215 pkt->nextWrite=!pkt->nextWrite;
216 aprintf("Read audio block, size=%d bytes, dts=%s\n",blk->sizeInBytes,ADM_us2plain(blk->dts));
217 return true;
218 }
219 /**
220 \fn writeAudioBlock
221 */
writeAudioBlock(int index,mp4v2AudioPacket::mp4v2AudioBlock * block,uint64_t nbSamples)222 bool muxerMp4v2::writeAudioBlock(int index,mp4v2AudioPacket::mp4v2AudioBlock *block,uint64_t nbSamples)
223 {
224 aprintf("Writting audio block : size=%d, samples=%d nbSamples=%d \n",block->sizeInBytes,block->nbSamples,(int)nbSamples);
225 bool r=MP4WriteSample(handle,audioTrackIds[index],
226 block->buffer,
227 block->sizeInBytes,
228 nbSamples,
229 0,1);
230 encoding->pushAudioFrame(block->sizeInBytes);
231 if(false==r)
232 {
233 ADM_error("Cannot write audio sample for track %d\n",index);
234 return false;
235 }
236 return true;
237 }
238 /**
239 \fn fillAudio
240 \brief push audio packets until nextDts is reached
241 */
fillAudio(uint64_t targetDts)242 bool muxerMp4v2::fillAudio(uint64_t targetDts)
243 {
244 for(int audioIndex=0;audioIndex<nbAStreams;audioIndex++)
245 {
246 ADM_audioStream *a=aStreams[audioIndex];
247 mp4v2AudioPacket *pkt=&(audioPackets[audioIndex]);
248 audioClock *clock=pkt->clock;
249 if(pkt->eos) continue;
250 uint64_t extraSamples=0;
251
252 WAVHeader *info=a->getInfo();
253 if(!info) // no more track
254 continue;
255 uint32_t fq=info->frequency;
256
257 while(1)
258 {
259 int current=!pkt->nextWrite;
260 int other=pkt->nextWrite;
261 mp4v2AudioPacket::mp4v2AudioBlock *currentBlock=&(pkt->blocks[current]);
262 mp4v2AudioPacket::mp4v2AudioBlock *otherBlock=&(pkt->blocks[other]);
263 // Get our currentDts
264 uint64_t currentDts=clock->getTimeUs();
265 uint64_t blockDts=currentBlock->dts;
266 if(pkt->eos) break;
267 extraSamples=0;
268 // Take either block Dts or our own if no DTS is provided
269 if(currentBlock->dts!=ADM_NO_PTS)
270 {
271 bprintf("Current audio Dts=%" PRId64"\n",currentDts);
272 bprintf("Incoming block, dts=%" PRId64"\n",currentBlock->dts);
273 bprintf("Delta =%d ms\n",(int)(currentDts-currentBlock->dts));
274 if( labs((long int)currentBlock->dts-(long int)currentDts)>MP4V2_MAX_JITTER)
275 {
276 if(currentBlock->dts<currentDts)
277 {
278 ADM_warning("Audio going back in time audio track %d\n",audioIndex);
279 ADM_warning("expected %d ms, got %d ms",currentDts/1000,currentBlock->dts/1000);
280 ADM_warning("Dropping packet\n");
281 goto nextOne;
282 }
283 // We have a hole, increase duration of current packet
284 double holeDurationUs=currentBlock->dts-currentDts;
285 ADM_warning("Hole detected in audio of %d ms, track %d\n",(int)(holeDurationUs/1000),audioIndex);
286 ADM_warning("we got a timing of %s",ADM_us2plain(currentBlock->dts));
287 ADM_warning("and expected %s\n",ADM_us2plain(currentDts));
288 holeDurationUs*=fq;
289 holeDurationUs/=1000*1000;
290 ADM_warning("Increasing hole duration by %d samples\n",(int)holeDurationUs);
291 extraSamples=(uint64_t)holeDurationUs;
292 }
293 }else
294 blockDts=currentDts;
295 if(blockDts>targetDts) // In the future
296 break;
297 if(false==writeAudioBlock(audioIndex,currentBlock,currentBlock->nbSamples+extraSamples))
298 {
299 ADM_error("Cannot write audio sample for track %d\n",audioIndex);
300 pkt->eos=true;
301 return false;
302 }
303 // load next
304
305 clock->advanceBySample(currentBlock->nbSamples+extraSamples);
306 nextOne:
307 if(false==loadAndToggleAudioSlot(audioIndex))
308 {
309 ADM_warning("End of audio stream %d\n",audioIndex);
310 #warning Purge other slot
311 pkt->eos=true;
312 }
313 }
314 }
315 return true;
316 }
317 //EOF
318
319
320
321