32 #include <QuickTime/QuickTime.h> 35 class QuickTimeFileReader::D
38 D() : data(0), blockSize(1024) { }
40 MovieAudioExtractionRef extractionSessionRef;
41 AudioBufferList buffer;
44 AudioStreamBasicDescription asbd;
50 QuickTimeFileReader::QuickTimeFileReader(
FileSource source,
51 DecodeMode decodeMode,
58 m_path(source.getLocalFilename()),
68 Profiler profiler(
"QuickTimeFileReader::QuickTimeFileReader",
true);
70 SVDEBUG <<
"QuickTimeFileReader: path is \"" << m_path <<
"\"" << endl;
77 m_d->err = Gestalt(gestaltQuickTime,&QTversion);
78 if ((m_d->err != noErr) || (QTversion < 0x07000000)) {
79 m_error = QString(
"Failed to find compatible version of QuickTime (version 7 or above required)");
93 QByteArray ba = m_path.toLocal8Bit();
95 CFURLRef url = CFURLCreateFromFileSystemRepresentation
97 (
const UInt8 *)ba.data(),
103 m_d->err = QTNewDataReferenceFromCFURL
104 (url, 0, &dataRef, &dataRefType);
107 m_error = QString(
"Error creating data reference for QuickTime decoder: code %1").arg(m_d->err);
111 short fileID = movieInDataForkResID;
113 m_d->err = NewMovieFromDataRef
114 (&m_d->movie, flags, &fileID, dataRef, dataRefType);
116 DisposeHandle(dataRef);
118 m_error = QString(
"Error creating new movie for QuickTime decoder: code %1").arg(m_d->err);
122 Boolean isProtected = 0;
123 Track aTrack = GetMovieIndTrackType
124 (m_d->movie, 1, SoundMediaType,
125 movieTrackMediaType | movieTrackEnabledOnly);
128 Media aMedia = GetTrackMedia(aTrack);
130 MediaHandler mh = GetMediaHandler(aMedia);
132 m_d->err = QTGetComponentProperty(mh,
133 kQTPropertyClass_DRM,
134 kQTDRMPropertyID_IsProtected,
135 sizeof(Boolean), &isProtected,nil);
146 if (m_d->err && m_d->err != kQTPropertyNotSupportedErr) {
147 m_error = QString(
"Error checking for DRM in QuickTime decoder: code %1").arg(m_d->err);
149 }
else if (!m_d->err && isProtected) {
150 m_error = QString(
"File is protected with DRM");
152 }
else if (m_d->err == kQTPropertyNotSupportedErr && !isProtected) {
153 cerr <<
"QuickTime: File is not protected with DRM" << endl;
157 SetMovieActive(m_d->movie, TRUE);
158 m_d->err = GetMoviesError();
160 m_error = QString(
"Error in QuickTime decoder activation: code %1").arg(m_d->err);
164 m_error = QString(
"Error in QuickTime decoder: Movie object not valid");
168 m_d->err = MovieAudioExtractionBegin
169 (m_d->movie, 0, &m_d->extractionSessionRef);
171 m_error = QString(
"Error in QuickTime decoder extraction init: code %1").arg(m_d->err);
175 m_d->err = MovieAudioExtractionGetProperty
176 (m_d->extractionSessionRef,
177 kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
183 m_error = QString(
"Error in QuickTime decoder property get: code %1").arg(m_d->err);
187 m_channelCount = m_d->asbd.mChannelsPerFrame;
188 m_fileRate = m_d->asbd.mSampleRate;
190 cerr <<
"QuickTime: " << m_channelCount <<
" channels, " << m_fileRate <<
" kHz" << endl;
192 m_d->asbd.mFormatFlags =
193 kAudioFormatFlagIsFloat |
194 kAudioFormatFlagIsPacked |
195 kAudioFormatFlagsNativeEndian;
196 m_d->asbd.mBitsPerChannel =
sizeof(float) * 8;
197 m_d->asbd.mBytesPerFrame =
sizeof(float) * m_d->asbd.mChannelsPerFrame;
198 m_d->asbd.mBytesPerPacket = m_d->asbd.mBytesPerFrame;
200 m_d->err = MovieAudioExtractionSetProperty
201 (m_d->extractionSessionRef,
202 kQTPropertyClass_MovieAudioExtraction_Audio,
203 kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
208 m_error = QString(
"Error in QuickTime decoder property set: code %1").arg(m_d->err);
212 m_d->buffer.mNumberBuffers = 1;
213 m_d->buffer.mBuffers[0].mNumberChannels = m_channelCount;
214 m_d->buffer.mBuffers[0].mDataByteSize =
215 sizeof(float) * m_channelCount * m_d->blockSize;
216 m_d->data =
new float[m_channelCount * m_d->blockSize];
217 m_d->buffer.mBuffers[0].mData = m_d->data;
219 initialiseDecodeCache();
221 if (decodeMode == DecodeAtOnce) {
224 connect(m_reporter, SIGNAL(cancelled()),
this, SLOT(cancelled()));
225 m_reporter->setMessage
226 (tr(
"Decoding %1...").arg(QFileInfo(m_path).fileName()));
231 UInt32 framesRead = m_d->blockSize;
232 UInt32 extractionFlags = 0;
233 m_d->err = MovieAudioExtractionFillBuffer
234 (m_d->extractionSessionRef, &framesRead, &m_d->buffer,
237 m_error = QString(
"Error in QuickTime decoding: code %1")
247 addSamplesToDecodeCache(m_d->data, framesRead);
249 if (framesRead < m_d->blockSize)
break;
255 m_d->err = MovieAudioExtractionEnd(m_d->extractionSessionRef);
257 m_error = QString(
"Error ending QuickTime extraction session: code %1").arg(m_d->err);
263 if (m_reporter) m_reporter->setProgress(100);
265 if (m_channelCount > 0) {
266 m_decodeThread =
new DecodeThread(
this);
267 m_decodeThread->start();
271 cerr <<
"QuickTimeFileReader::QuickTimeFileReader: frame count is now " << getFrameCount() <<
", error is \"\"" << m_error <<
"\"" << endl;
274 QuickTimeFileReader::~QuickTimeFileReader()
276 SVDEBUG <<
"QuickTimeFileReader::~QuickTimeFileReader" << endl;
278 if (m_decodeThread) {
280 m_decodeThread->wait();
281 delete m_decodeThread;
284 SetMovieActive(m_d->movie, FALSE);
285 DisposeMovie(m_d->movie);
292 QuickTimeFileReader::cancelled()
298 QuickTimeFileReader::DecodeThread::run()
300 if (m_reader->m_cacheMode == CacheInTemporaryFile) {
301 m_reader->m_completion = 1;
302 m_reader->startSerialised(
"QuickTimeFileReader::Decode");
307 UInt32 framesRead = m_reader->m_d->blockSize;
308 UInt32 extractionFlags = 0;
309 m_reader->m_d->err = MovieAudioExtractionFillBuffer
310 (m_reader->m_d->extractionSessionRef, &framesRead,
311 &m_reader->m_d->buffer, &extractionFlags);
312 if (m_reader->m_d->err) {
313 m_reader->m_error = QString(
"Error in QuickTime decoding: code %1")
314 .arg(m_reader->m_d->err);
319 m_reader->addSamplesToDecodeCache(m_reader->m_d->data, framesRead);
321 if (framesRead < m_reader->m_d->blockSize)
break;
324 m_reader->finishDecodeCache();
326 m_reader->m_d->err = MovieAudioExtractionEnd(m_reader->m_d->extractionSessionRef);
327 if (m_reader->m_d->err) {
328 m_reader->m_error = QString(
"Error ending QuickTime extraction session: code %1").arg(m_reader->m_d->err);
331 m_reader->m_completion = 100;
332 m_reader->endSerialised();
336 QuickTimeFileReader::getSupportedExtensions(std::set<QString> &extensions)
338 extensions.insert(
"aiff");
339 extensions.insert(
"aif");
340 extensions.insert(
"au");
341 extensions.insert(
"avi");
342 extensions.insert(
"m4a");
343 extensions.insert(
"m4b");
344 extensions.insert(
"m4p");
345 extensions.insert(
"m4v");
346 extensions.insert(
"mov");
347 extensions.insert(
"mp3");
348 extensions.insert(
"mp4");
349 extensions.insert(
"wav");
353 QuickTimeFileReader::supportsExtension(QString extension)
355 std::set<QString> extensions;
356 getSupportedExtensions(extensions);
357 return (extensions.find(extension.toLower()) != extensions.end());
361 QuickTimeFileReader::supportsContentType(QString type)
363 return (type ==
"audio/x-aiff" ||
364 type ==
"audio/x-wav" ||
365 type ==
"audio/mpeg" ||
366 type ==
"audio/basic" ||
367 type ==
"audio/x-aac" ||
368 type ==
"video/mp4" ||
369 type ==
"video/quicktime");
373 QuickTimeFileReader::supports(
FileSource &source)
QString getExtension() const
Return the file extension for this file, if any.
FileSource is a class used to refer to the contents of a file that may be either local or at a remote...
QString getContentType() const
Return the MIME content type of this file, if known.
Profile point instance class.