Mercurial > hg > svcore
comparison data/fileio/QuickTimeFileReader.cpp @ 282:e2fdcf9d35c5
* Make QuickTime file reader work (has been tested)
author | Chris Cannam |
---|---|
date | Wed, 08 Aug 2007 12:03:35 +0000 |
parents | 9c447d664275 |
children | 20028c634494 |
comparison
equal
deleted
inserted
replaced
281:9c447d664275 | 282:e2fdcf9d35c5 |
---|---|
38 public: | 38 public: |
39 D() : data(0), blockSize(1024) { } | 39 D() : data(0), blockSize(1024) { } |
40 | 40 |
41 MovieAudioExtractionRef extractionSessionRef; | 41 MovieAudioExtractionRef extractionSessionRef; |
42 AudioBufferList buffer; | 42 AudioBufferList buffer; |
43 float *data; | 43 double *data; |
44 OSErr err; | 44 OSErr err; |
45 AudioStreamBasicDescription asbd; | 45 AudioStreamBasicDescription asbd; |
46 Movie movie; | 46 Movie movie; |
47 size_t blockSize; | 47 size_t blockSize; |
48 }; | 48 }; |
63 m_channelCount = 0; | 63 m_channelCount = 0; |
64 m_sampleRate = 0; | 64 m_sampleRate = 0; |
65 | 65 |
66 Profiler profiler("QuickTimeFileReader::QuickTimeFileReader", true); | 66 Profiler profiler("QuickTimeFileReader::QuickTimeFileReader", true); |
67 | 67 |
68 std::cerr << "QuickTimeFileReader: path is \"" << path.toStdString() << "\"" << std::endl; | |
69 | |
68 long QTversion; | 70 long QTversion; |
69 | 71 |
70 #ifdef WIN32 | 72 #ifdef WIN32 |
71 InitializeQTML(0); // FIXME should check QT version | 73 InitializeQTML(0); // FIXME should check QT version |
72 #else | 74 #else |
80 EnterMovies(); | 82 EnterMovies(); |
81 | 83 |
82 Handle dataRef; | 84 Handle dataRef; |
83 OSType dataRefType; | 85 OSType dataRefType; |
84 | 86 |
85 CFStringRef URLString = CFStringCreateWithCString | 87 // CFStringRef URLString = CFStringCreateWithCString |
86 (0, m_path.toLocal8Bit().data(), 0); | 88 // (0, m_path.toLocal8Bit().data(), 0); |
87 | 89 |
88 m_d->err = QTNewDataReferenceFromURLCFString | 90 |
89 (URLString, 0, &dataRef, &dataRefType); | 91 CFURLRef url = CFURLCreateFromFileSystemRepresentation |
92 (kCFAllocatorDefault, | |
93 (const UInt8 *)path.toLocal8Bit().data(), | |
94 (CFIndex)path.length(), | |
95 false); | |
96 | |
97 | |
98 // m_d->err = QTNewDataReferenceFromURLCFString | |
99 m_d->err = QTNewDataReferenceFromCFURL | |
100 (url, 0, &dataRef, &dataRefType); | |
90 | 101 |
91 if (m_d->err) { | 102 if (m_d->err) { |
92 m_error = QString("Error creating data reference for QuickTime decoder: code %1").arg(m_d->err); | 103 m_error = QString("Error creating data reference for QuickTime decoder: code %1").arg(m_d->err); |
93 return; | 104 return; |
94 } | 105 } |
143 m_d->err = GetMoviesError(); | 154 m_d->err = GetMoviesError(); |
144 if (m_d->err) { | 155 if (m_d->err) { |
145 m_error = QString("Error in QuickTime decoder activation: code %1").arg(m_d->err); | 156 m_error = QString("Error in QuickTime decoder activation: code %1").arg(m_d->err); |
146 return; | 157 return; |
147 } | 158 } |
159 } else { | |
160 m_error = QString("Error in QuickTime decoder: Movie object not valid"); | |
161 return; | |
148 } | 162 } |
149 | 163 |
150 m_d->err = MovieAudioExtractionBegin | 164 m_d->err = MovieAudioExtractionBegin |
151 (m_d->movie, 0, &m_d->extractionSessionRef); | 165 (m_d->movie, 0, &m_d->extractionSessionRef); |
152 if (m_d->err) { | 166 if (m_d->err) { |
153 m_error = QString("Error in QuickTime decoder extraction init: code %1").arg(m_d->err); | 167 m_error = QString("Error in QuickTime decoder extraction init: code %1").arg(m_d->err); |
154 return; | 168 return; |
155 } | 169 } |
156 /* | |
157 AudioChannelLayout monoLayout = {0}; | |
158 monoLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; | |
159 m_d->err = MovieAudioExtractionSetProperty(m_d->extractionSessionRef, | |
160 kQTPropertyClass_MovieAudioExtraction_Audio, | |
161 kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |
162 sizeof(monoLayout), &monoLayout); | |
163 if (m_d->err) { | |
164 m_error = QString("Error in QuickTime decoder property set: code %1").arg(m_d->err); | |
165 return; | |
166 } | |
167 */ | |
168 | 170 |
169 m_d->err = MovieAudioExtractionGetProperty | 171 m_d->err = MovieAudioExtractionGetProperty |
170 (m_d->extractionSessionRef, | 172 (m_d->extractionSessionRef, |
171 kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | 173 kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, |
172 sizeof(m_d->asbd), | 174 sizeof(m_d->asbd), |
185 | 187 |
186 m_d->asbd.mFormatFlags = | 188 m_d->asbd.mFormatFlags = |
187 kAudioFormatFlagIsFloat | | 189 kAudioFormatFlagIsFloat | |
188 kAudioFormatFlagIsPacked | | 190 kAudioFormatFlagIsPacked | |
189 kAudioFormatFlagsNativeEndian; | 191 kAudioFormatFlagsNativeEndian; |
190 m_d->asbd.mBitsPerChannel = sizeof(float) * 8; | 192 m_d->asbd.mBitsPerChannel = sizeof(double) * 8; |
191 m_d->asbd.mBytesPerFrame = sizeof(float) * m_d->asbd.mChannelsPerFrame; | 193 m_d->asbd.mBytesPerFrame = sizeof(double) * m_d->asbd.mChannelsPerFrame; |
192 m_d->asbd.mBytesPerPacket = m_d->asbd.mBytesPerFrame; | 194 m_d->asbd.mBytesPerPacket = m_d->asbd.mBytesPerFrame; |
193 | 195 |
194 m_d->err = MovieAudioExtractionSetProperty | 196 m_d->err = MovieAudioExtractionSetProperty |
195 (m_d->extractionSessionRef, | 197 (m_d->extractionSessionRef, |
196 kQTPropertyClass_MovieAudioExtraction_Audio, | 198 kQTPropertyClass_MovieAudioExtraction_Audio, |
197 kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | 199 kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, |
198 sizeof(m_d->asbd), | 200 sizeof(m_d->asbd), |
199 &m_d->asbd); | 201 &m_d->asbd); |
200 | 202 |
201 if (m_d->err) { | 203 if (m_d->err) { |
202 m_error = QString("Error in QuickTime decoder ASBD set: code %1").arg(m_d->err); | 204 m_error = QString("Error in QuickTime decoder property set: code %1").arg(m_d->err); |
203 return; | 205 return; |
204 } | 206 } |
205 | 207 |
206 m_d->buffer.mNumberBuffers = 1; | 208 m_d->buffer.mNumberBuffers = 1; |
207 m_d->buffer.mBuffers[0].mNumberChannels = m_channelCount; | 209 m_d->buffer.mBuffers[0].mNumberChannels = m_channelCount; |
208 m_d->buffer.mBuffers[0].mDataByteSize = | 210 m_d->buffer.mBuffers[0].mDataByteSize = |
209 sizeof(float) * m_channelCount * m_d->blockSize; | 211 sizeof(double) * m_channelCount * m_d->blockSize; |
210 m_d->data = new float[m_d->blockSize]; | 212 m_d->data = new double[m_channelCount * m_d->blockSize]; |
211 m_d->buffer[0].mData = m_d->data; | 213 m_d->buffer.mBuffers[0].mData = m_d->data; |
212 | 214 |
213 initialiseDecodeCache(); | 215 initialiseDecodeCache(); |
214 | 216 |
215 if (decodeMode == DecodeAtOnce) { | 217 if (decodeMode == DecodeAtOnce) { |
216 | 218 |
219 QObject::tr("Stop"), 0, 100); | 221 QObject::tr("Stop"), 0, 100); |
220 m_progress->hide(); | 222 m_progress->hide(); |
221 | 223 |
222 while (1) { | 224 while (1) { |
223 | 225 |
224 UInt32 framesRead = 0; | 226 UInt32 framesRead = m_d->blockSize; |
225 UInt32 extractionFlags = 0; | 227 UInt32 extractionFlags = 0; |
226 m_d->err = MovieAudioExtractionFillBuffer | 228 m_d->err = MovieAudioExtractionFillBuffer |
227 (m_d->extractionSessionRef, &framesRead, &m_d->buffer, | 229 (m_d->extractionSessionRef, &framesRead, &m_d->buffer, |
228 &extractionFlags); | 230 &extractionFlags); |
229 if (m_d->err) { | 231 if (m_d->err) { |
230 m_error = QString("Error in QuickTime decoding: code %1") | 232 m_error = QString("Error in QuickTime decoding: code %1") |
231 .arg(m_d->err); | 233 .arg(m_d->err); |
232 break; | 234 break; |
233 } | 235 } |
234 | 236 |
237 // std::cerr << "Read " << framesRead << " frames (block size " << m_d->blockSize << ")" << std::endl; | |
238 | |
239 m_frameCount += framesRead; | |
240 | |
235 // QuickTime buffers are interleaved unless specified otherwise | 241 // QuickTime buffers are interleaved unless specified otherwise |
236 for (UInt32 i = 0; i < framesRead * m_channelCount; ++i) { | 242 for (UInt32 i = 0; i < framesRead * m_channelCount; ++i) { |
237 addSampleToDecodeCache(m_d->data[i]); | 243 addSampleToDecodeCache(m_d->data[i]); |
238 } | 244 } |
239 | 245 |
256 if (m_channelCount > 0) { | 262 if (m_channelCount > 0) { |
257 m_decodeThread = new DecodeThread(this); | 263 m_decodeThread = new DecodeThread(this); |
258 m_decodeThread->start(); | 264 m_decodeThread->start(); |
259 } | 265 } |
260 } | 266 } |
267 | |
268 std::cerr << "QuickTimeFileReader::QuickTimeFileReader: frame count is now " << getFrameCount() << ", error is \"\"" << m_error.toStdString() << "\"" << std::endl; | |
261 } | 269 } |
262 | 270 |
263 QuickTimeFileReader::~QuickTimeFileReader() | 271 QuickTimeFileReader::~QuickTimeFileReader() |
264 { | 272 { |
273 std::cerr << "QuickTimeFileReader::~QuickTimeFileReader" << std::endl; | |
274 | |
265 if (m_decodeThread) { | 275 if (m_decodeThread) { |
266 m_cancelled = true; | 276 m_cancelled = true; |
267 m_decodeThread->wait(); | 277 m_decodeThread->wait(); |
268 delete m_decodeThread; | 278 delete m_decodeThread; |
269 } | 279 } |
270 | 280 |
271 SetMovieActive(m_d->movie); | 281 SetMovieActive(m_d->movie, FALSE); |
272 DisposeMovie(m_d->movie); | 282 DisposeMovie(m_d->movie); |
273 | 283 |
274 delete[] m_d->data; | 284 delete[] m_d->data; |
275 delete m_d; | 285 delete m_d; |
276 } | 286 } |
278 void | 288 void |
279 QuickTimeFileReader::DecodeThread::run() | 289 QuickTimeFileReader::DecodeThread::run() |
280 { | 290 { |
281 while (1) { | 291 while (1) { |
282 | 292 |
283 UInt32 framesRead = 0; | 293 UInt32 framesRead = m_reader->m_d->blockSize; |
284 UInt32 extractionFlags = 0; | 294 UInt32 extractionFlags = 0; |
285 m_reader->m_d->err = MovieAudioExtractionFillBuffer | 295 m_reader->m_d->err = MovieAudioExtractionFillBuffer |
286 (m_reader->m_d->extractionSessionRef, &framesRead, | 296 (m_reader->m_d->extractionSessionRef, &framesRead, |
287 &m_reader->m_d->buffer, &extractionFlags); | 297 &m_reader->m_d->buffer, &extractionFlags); |
288 if (m_reader->m_d->err) { | 298 if (m_reader->m_d->err) { |
289 m_error = QString("Error in QuickTime decoding: code %1") | 299 m_reader->m_error = QString("Error in QuickTime decoding: code %1") |
290 .arg(m_reader->m_d->err); | 300 .arg(m_reader->m_d->err); |
291 break; | 301 break; |
292 } | 302 } |
293 | 303 |
304 m_reader->m_frameCount += framesRead; | |
305 | |
294 // QuickTime buffers are interleaved unless specified otherwise | 306 // QuickTime buffers are interleaved unless specified otherwise |
295 for (UInt32 i = 0; i < framesRead * m_channelCount; ++i) { | 307 for (UInt32 i = 0; i < framesRead * m_reader->m_channelCount; ++i) { |
296 addSampleToDecodeCache(m_reader->m_d->data[i]); | 308 m_reader->addSampleToDecodeCache(m_reader->m_d->data[i]); |
297 } | 309 } |
298 | 310 |
299 if (framesRead < m_reader->m_d->blockSize) break; | 311 if (framesRead < m_reader->m_d->blockSize) break; |
300 } | 312 } |
301 | 313 |