1 /***************************************************************************
2 \fn ADMedAVIAUD.cpp
3 \brief Interface to audio track(s) from editor
4
5 Handle switching from pieces of movie
6 Also fix the gap/overlap in audio to offer a strictly continuous audio stream
7
8 copyright : (C) 2008/2009 by mean
9 email : fixounet@free.fr
10
11 Todo:
12 -----
13 x Fix handling of overlay/gap, it is wrong.
14
15
16 ***************************************************************************/
17
18 /***************************************************************************
19 * *
20 * This program is free software; you can redistribute it and/or modify *
21 * it under the terms of the GNU General Public License as published by *
22 * the Free Software Foundation; either version 2 of the License, or *
23 * (at your option) any later version. *
24 * *
25 ***************************************************************************/
26
27 #include <string.h>
28 #include "ADM_cpp.h"
29 #include "ADM_default.h"
30 #include <math.h>
31
32 #include "fourcc.h"
33 #include "ADM_edit.hxx"
34 #include "ADM_edAudioTrackFromVideo.h"
35 #include "ADM_vidMisc.h"
36
37 #ifdef _MSC_VER
38 #define abs(x) _abs64(x)
39 #endif
40
41 #if 1
42 #define vprintf(...) {}
43 #else
44 #define vprintf printf
45 #endif
46 /**
47 \fn getOutputFrequency
48 \brief Get output fq, 2*wavheader->fq for sbr
49
50 */
51
getOutputFrequency(void)52 uint32_t ADM_edAudioTrackFromVideo::getOutputFrequency(void)
53 {
54 ADM_audioStreamTrack *trk=getCurrentTrack();
55 if(!trk)
56 {
57 ADM_warning("No audio track\n");
58 return 0;
59 }
60 if(!trk->codec)
61 return trk->wavheader.frequency;
62 return trk->codec->getOutputFrequency();
63 }
64
65 /**
66 \fn getOutputChannels
67 \brief get nb of channels as seen by codec
68 */
getOutputChannels(void)69 uint32_t ADM_edAudioTrackFromVideo::getOutputChannels(void)
70 {
71 ADM_audioStreamTrack *trk=getCurrentTrack();
72 if(!trk)
73 {
74 ADM_warning("No audio track\n");
75 return 0;
76 }
77 if(!trk->codec)
78 return trk->wavheader.channels;
79 return trk->codec->getOutputChannels();
80 }
81
82 /**
83 \fn getPCMPacket
84 \brief Get audio packet
85
86 */
87
getPCMPacket(float * dest,uint32_t sizeMax,uint32_t * samples,uint64_t * odts)88 bool ADM_edAudioTrackFromVideo::getPCMPacket(float *dest, uint32_t sizeMax, uint32_t *samples,uint64_t *odts)
89 {
90 uint32_t fillerSample=0; // FIXME : Store & fix the DTS error correctly!!!!
91 bool drop=false;
92 bool checkDts;
93 static bool fail=false;
94 uint32_t outFrequency=getOutputFrequency();
95 uint32_t outChannels=getOutputChannels();
96
97 if(!outChannels) return false;
98
99 vprintf("[PCMPacket] request TRK %d:%x\n",myTrackNumber,(long int)getCurrentTrack());
100 again:
101 *samples=0;
102 ADM_audioStreamTrack *trk=getCurrentTrack();
103 if(!trk) return false;
104 if(trk->codec->isDummy()) return false;
105 checkDts=(trk->stream->constantSamplesPerPacket() && !trk->isbr);
106 // Do we already have a packet ?
107 if(!packetBufferSize)
108 {
109 if(!refillPacketBuffer())
110 {
111 if(fail==false)
112 ADM_warning("[Editor] Cannot refill audio\n");
113 fail=true;
114 return false;
115 }
116 }
117 // We do now
118 vprintf("[PCMPacket] TRK %d Got %d samples, time code %08" PRIu64" lastDts=%08" PRIu64" delta =%" PRId64"\n",
119 myTrackNumber,packetBufferSamples,packetBufferDts,lastDts,packetBufferDts-lastDts);
120 fail=false;
121
122 // Check if the Dts matches
123 if(checkDts && lastDts!=ADM_AUDIO_NO_DTS &&packetBufferDts!=ADM_AUDIO_NO_DTS)
124 {
125 if(labs((int64_t)lastDts-(int64_t)packetBufferDts)>ADM_ALLOWED_DRIFT_US)
126 {
127 printf("[Composer::getPCMPacket] Track %d, %p ", (int)myTrackNumber,trk);
128 printf(": drift %d, computed : %s", (int)(lastDts-packetBufferDts),ADM_us2plain(lastDts));
129 printf(" got %s\n", ADM_us2plain(packetBufferDts));
130 if(packetBufferDts<lastDts)
131 {
132 printf("[Composer::getPCMPacket] Track %d:%" PRIx64" : Dropping packet %" PRIu32" last =%" PRIu32"\n",myTrackNumber,(uint64_t)trk,(uint32_t)(lastDts/1000),(uint32_t)(packetBufferDts/1000));
133 drop=true;
134 }else
135 {
136 // There is a "hole" in audio
137 // Let's add some filler
138 // Compute filler size
139 *odts=lastDts;
140 float f=packetBufferDts-lastDts; // in us
141 f*=outFrequency;
142 f/=1000000.;
143 // in samples!
144 uint32_t fillerSample=(uint32_t )(f+0.49);
145 uint32_t mx=sizeMax/outChannels;
146
147 if(mx<fillerSample) fillerSample=mx;
148 // arbitrary cap, max 4kSample in one go
149 // about 100 ms
150 if(fillerSample>4*1024)
151 {
152 fillerSample=4*1024;
153 }
154 uint32_t start=fillerSample*sizeof(float)*outChannels;
155 memset(dest,0,start);
156
157 advanceDtsByCustomSample(fillerSample,outFrequency);
158 dest+=fillerSample*outChannels;
159 *samples=fillerSample;
160 vprintf("[Composer::getPCMPacket] Track %d:%x Adding %u padding samples, dts is now %lu\n",
161 myTrackNumber,(long int)trk,fillerSample,lastDts);
162 return true;
163 }
164 }
165 }
166 // If lastDts is not initialized....
167 if(lastDts==ADM_AUDIO_NO_DTS) lastDts=packetBufferDts;
168
169 //
170 // The packet is ok, decode it...
171 //
172 uint32_t nbOut=0; // Nb sample as seen by codec
173 if(!trk->codec->run(packetBuffer, packetBufferSize, dest, &nbOut))
174 {
175 packetBufferSize=0; // consume
176 ADM_warning("Track %d at 0x%p : decoding failed\n",myTrackNumber,trk);
177 return false;
178 }
179 packetBufferSize=0; // consume
180
181 // Compute how much decoded sample to compare with what demuxer said
182 uint32_t decodedSample=nbOut;
183 decodedSample/=outChannels;
184 if(!decodedSample) goto again;
185 #define ADM_MAX_JITTER 5000 // in samples, due to clock accuracy, it can be +er, -er, + er, -er etc etc
186 if(checkDts && labs((int64_t)decodedSample-(int64_t)packetBufferSamples)>ADM_MAX_JITTER)
187 {
188 ADM_warning("[Composer::getPCMPacket] Track %d:%x Demuxer was wrong %d vs %d samples!\n",
189 myTrackNumber,trk,packetBufferSamples,decodedSample);
190 }
191
192 // This packet has been dropped (too early packt), try the next one
193 if(drop==true)
194 {
195 // TODO Check if the packet somehow overlaps, i.e. starts too early but finish ok
196 goto again;
197 }
198 // Update infos
199 *samples=(decodedSample);
200 *odts=lastDts;
201 advanceDtsByCustomSample(decodedSample,outFrequency);
202 vprintf("[Composer::getPCMPacket] Track %d:%p Adding %u decoded, Adding %u filler sample, dts is now %" PRIu64", fq: %d\n",
203 myTrackNumber,trk,decodedSample,fillerSample,lastDts,outFrequency);
204 ADM_assert(sizeMax>=(fillerSample+decodedSample)*outChannels);
205 return true;
206 }
207
208
209 //EOF
210
211