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 #if 0
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 */
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("", "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("","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("","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 */
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","Cannot get AAC Extra data\n");
134                                  return false;
135                             }
136                         audioTrackIds[i]=MP4AddAudioTrack(handle,
137                                                       header->frequency,
138                                                       1024,
139                                                       MP4_MPEG4_AUDIO_TYPE);
140                         if(MP4_INVALID_TRACK_ID==audioTrackIds[i])
141                         {
142                             ADM_error("Error adding audio track %i of type 0x%x\n",i,header->encoding);
143                             return false;
144                         }
145                         aprintf("Add Track %d fq %d\n",audioTrackIds[i],header->frequency);
146                         MP4SetAudioProfileLevel(handle,0x0f);
147                         MP4SetTrackIntegerProperty(handle,audioTrackIds[i],"mdia.minf.stbl.stsd.mp4a.channels",
148                                     header->channels);
149                         MP4SetTrackESConfiguration(handle,audioTrackIds[i],extraData,extraDataLen);
150                     break;
151                     }
152             case WAV_AC3:
153                     if(false==addAc3(i, header))
154                     {
155                             return false;
156                     }
157                     break;
158             case WAV_MP2:
159             case WAV_MP3:
160                     audioTrackIds[i]=MP4AddAudioTrack(handle,
161                                                       header->frequency,
162                                                       audioPackets[i].blocks[0].nbSamples,
163                                                       MP4_MPEG2_AUDIO_TYPE);
164                     if(MP4_INVALID_TRACK_ID==audioTrackIds[i])
165                     {
166                         ADM_error("Error adding audio track %i of type 0x%x\n",i,header->encoding);
167                         return false;
168                     }
169                     aprintf("Add Track %d fq %d\n",audioTrackIds[i],header->frequency);
170                     MP4SetAudioProfileLevel(handle,0x0f);
171                     MP4SetTrackIntegerProperty(handle,audioTrackIds[i],"mdia.minf.stbl.stsd.mp4a.channels",
172                                 header->channels);
173                     break;
174             default:
175                     ADM_error("Cannot create audio track of type 0x%x\n",header->encoding);
176                     return false;
177         }
178          MP4SetTrackBytesProperty(handle,audioTrackIds[i],"udta.name.value",
179                     (const uint8_t*)"Stereo", strlen("Stereo"));
180 
181     }
182     if(nbAStreams)
183          MP4SetTrackIntegerProperty(handle, audioTrackIds[0], "tkhd.flags", 3);
184     return true;
185 }
186 /**
187     \fn loadAndToggleAudioSlot
188 */
189 bool muxerMp4v2::loadAndToggleAudioSlot(int index)
190 {
191         ADM_audioStream                     *a=aStreams[index];
192         mp4v2AudioPacket                    *pkt=&(audioPackets[index]);
193         mp4v2AudioPacket::mp4v2AudioBlock   *blk=&(pkt->blocks[pkt->nextWrite]);
194         if(!a->getPacket(blk->buffer,
195                          &(blk->sizeInBytes),
196                          AUDIO_BUFFER_SIZE,
197                          &(blk->nbSamples),
198                          &(blk->dts)))
199         {
200                 ADM_warning("Cannot get audio packet for stream %d\n",index);
201                 pkt->eos=true;
202                 return false;
203         }
204         if(blk->dts!=ADM_NO_PTS)
205             blk->dts+=audioDelay;
206         blk->present=true;
207         pkt->nextWrite=!pkt->nextWrite;
208         aprintf("Read audio block, size=%d bytes, dts=%s\n",blk->sizeInBytes,ADM_us2plain(blk->dts));
209         return true;
210 }
211 /**
212     \fn writeAudioBlock
213 */
214 bool muxerMp4v2::writeAudioBlock(int index,mp4v2AudioPacket::mp4v2AudioBlock *block,uint64_t nbSamples)
215 {
216     aprintf("Writting audio block : size=%d, samples=%d nbSamples=%d \n",block->sizeInBytes,block->nbSamples,(int)nbSamples);
217     bool r=MP4WriteSample(handle,audioTrackIds[index],
218                             block->buffer,
219                             block->sizeInBytes,
220                             nbSamples,
221                             0,1);
222     encoding->pushAudioFrame(block->sizeInBytes);
223     if(false==r)
224                         {
225                             ADM_error("Cannot write audio sample for track %d\n",index);
226                             return false;
227                         }
228     return true;
229 }
230 /**
231     \fn fillAudio
232     \brief push audio packets until nextDts is reached
233 */
234 bool muxerMp4v2::fillAudio(uint64_t targetDts)
235 {
236     for(int audioIndex=0;audioIndex<nbAStreams;audioIndex++)
237     {
238                 ADM_audioStream         *a=aStreams[audioIndex];
239                 uint32_t                fq=a->getInfo()->frequency;
240                 mp4v2AudioPacket       *pkt=&(audioPackets[audioIndex]);
241                 audioClock             *clock=pkt->clock;
242                 if(pkt->eos)            continue;
243                 uint64_t                extraSamples=0;
244                 while(1)
245                 {
246                         int current=!pkt->nextWrite;
247                         int other=pkt->nextWrite;
248                         mp4v2AudioPacket::mp4v2AudioBlock        *currentBlock=&(pkt->blocks[current]);
249                         mp4v2AudioPacket::mp4v2AudioBlock        *otherBlock=&(pkt->blocks[other]);
250                         // Get our currentDts
251                         uint64_t currentDts=clock->getTimeUs();
252                         uint64_t blockDts=currentBlock->dts;
253                         if(pkt->eos)            break;
254                         extraSamples=0;
255                         // Take either block Dts or our own if no DTS is provided
256                         if(currentBlock->dts!=ADM_NO_PTS)
257                         {
258                             bprintf("Current audio Dts=%"PRId64"\n",currentDts);
259                             bprintf("Incoming block, dts=%"PRId64"\n",currentBlock->dts);
260                             bprintf("Delta =%d ms\n",(int)(currentDts-currentBlock->dts));
261                             if( abs(currentBlock->dts-currentDts)>MP4V2_MAX_JITTER)
262                             {
263                                 if(currentBlock->dts<currentDts)
264                                     {
265                                             ADM_warning("Audio going back in time audio track %d\n",audioIndex);
266                                             ADM_warning("expected %d ms, got %d ms",currentDts/1000,currentBlock->dts/1000);
267                                             ADM_warning("Dropping packet\n");
268                                             goto nextOne;
269                                     }
270                                 // We have a hole, increase duration of current packet
271                                 double holeDurationUs=currentBlock->dts-currentDts;
272                                 ADM_warning("Hole detected in audio of %d ms, track %d\n",(int)(holeDurationUs/1000),audioIndex);
273                                 ADM_warning("we got a timing of %s",ADM_us2plain(currentBlock->dts));
274                                 ADM_warning("and expected %s\n",ADM_us2plain(currentDts));
275                                 holeDurationUs*=fq;
276                                 holeDurationUs/=1000*1000;
277                                 ADM_warning("Increasing hole duration by %d samples\n",(int)holeDurationUs);
278                                 extraSamples=(uint64_t)holeDurationUs;
279                             }
280                         }else
281                             blockDts=currentDts;
282                         if(blockDts>targetDts) // In the future
283                             break;
284                         if(false==writeAudioBlock(audioIndex,currentBlock,currentBlock->nbSamples+extraSamples))
285                         {
286                             ADM_error("Cannot write audio sample for track %d\n",audioIndex);
287                             pkt->eos=true;
288                             return false;
289                         }
290                         // load next
291 
292                         clock->advanceBySample(currentBlock->nbSamples+extraSamples);
293 nextOne:
294                         if(false==loadAndToggleAudioSlot(audioIndex))
295                         {
296                             ADM_warning("End of audio stream %d\n",audioIndex);
297                             #warning Purge other slot
298                             pkt->eos=true;
299                         }
300                 }
301     }
302     return true;
303 }
304 #endif
305 //EOF
306 
307 
308 
309