コード例 #1
0
ComponentResult initVorbisComponent(WebMExportGlobalsPtr globals, GenericStreamPtr as)
{
    dbg_printf("[WebM] enter initVorbisComponent\n");
    ComponentResult err = noErr;
    if (globals->audioSettingsAtom == NULL)
        getDefaultVorbisAtom(globals);

    //This chunk initializes the Component instance that will be used for decompression  : TODO put this in its own function
    err = OpenADefaultComponent(StandardCompressionType, StandardCompressionSubTypeAudio, &as->aud.vorbisComponentInstance);

    if (err) goto bail;

    AudioStreamBasicDescription *inFormat = NULL;
    inFormat = calloc(1, sizeof(AudioStreamBasicDescription));

    if (inFormat == NULL) goto bail;

    err = getInputBasicDescription(as, inFormat);

    if (err) goto bail;

    getInputBasicDescription(as, inFormat);


    err = SCSetSettingsFromAtomContainer(as->aud.vorbisComponentInstance, globals->audioSettingsAtom);

    if (err) goto bail;

    err = QTGetComponentProperty(as->aud.vorbisComponentInstance, kQTPropertyClass_SCAudio,
                                 kQTSCAudioPropertyID_BasicDescription,
                                 sizeof(AudioStreamBasicDescription), &as->aud.asbd, NULL);

    if (err) goto bail;

    err = QTSetComponentProperty(as->aud.vorbisComponentInstance,  kQTPropertyClass_SCAudio, kQTSCAudioPropertyID_InputBasicDescription,
                                 sizeof(AudioStreamBasicDescription), inFormat);
bail:

    if (inFormat != NULL)
        free(inFormat);

    dbg_printf("[WebM]initVorbisComponent return %d\n", err);
    return err;
}
コード例 #2
0
static void _initAudioBufferList(GenericStreamPtr as, AudioBufferList **audioBufferList, UInt32 ioPackets)
{
  int i;

  UInt32 maxBytesPerPacket = 4096;
  ComponentResult err = noErr;

  err = QTGetComponentProperty(as->aud.vorbisComponentInstance, kQTPropertyClass_SCAudio,
                             kQTSCAudioPropertyID_MaximumOutputPacketSize,
                                 sizeof(maxBytesPerPacket), &maxBytesPerPacket, NULL);
  if (err)
  {
    dbg_printf("[Webm] Error getting max Bytes per packet\n");
    maxBytesPerPacket = 255 *255;  //this should be roughly valid for ogg Vorbis
    err = noErr;
  }

  UInt32 bufferListSize = offsetof(AudioBufferList, mBuffers[ioPackets]);

  dbg_printf("[WebM]Calling InitAudioBufferList size %ld, each buffer being %lu\n", bufferListSize, maxBytesPerPacket);

  *audioBufferList = (AudioBufferList *) malloc(bufferListSize);
  (*audioBufferList)->mNumberBuffers = ioPackets;
  UInt32 wantedSize = maxBytesPerPacket * ioPackets;

  if (as->aud.buf.data == NULL || as->aud.buf.size != wantedSize)
  {
    as->aud.buf.data = realloc(as->aud.buf.data, wantedSize);
    as->aud.buf.size = wantedSize;
    as->aud.buf.offset = 0;
  }

  for (i = 0; i < ioPackets; i++)
  {
    (*audioBufferList)->mBuffers[i].mNumberChannels = as->aud.asbd.mChannelsPerFrame;
    (*audioBufferList)->mBuffers[i].mDataByteSize = maxBytesPerPacket;
    (*audioBufferList)->mBuffers[i].mData = (void *)((unsigned char *)as->aud.buf.data + maxBytesPerPacket * i);
  }
}
コード例 #3
0
QuickTimeFileReader::QuickTimeFileReader(FileSource source,
                                         DecodeMode decodeMode,
                                         CacheMode mode,
                                         size_t targetRate,
                                         ProgressReporter *reporter) :
    CodedAudioFileReader(mode, targetRate),
    m_source(source),
    m_path(source.getLocalFilename()),
    m_d(new D),
    m_reporter(reporter),
    m_cancelled(false),
    m_completion(0),
    m_decodeThread(0)
{
    m_channelCount = 0;
    m_fileRate = 0;

    Profiler profiler("QuickTimeFileReader::QuickTimeFileReader", true);

SVDEBUG << "QuickTimeFileReader: path is \"" << m_path << "\"" << endl;

    long QTversion;

#ifdef WIN32
    InitializeQTML(0); // FIXME should check QT version
#else
    m_d->err = Gestalt(gestaltQuickTime,&QTversion);
    if ((m_d->err != noErr) || (QTversion < 0x07000000)) {
        m_error = QString("Failed to find compatible version of QuickTime (version 7 or above required)");
        return;
    }
#endif 

    EnterMovies();
	
    Handle dataRef; 
    OSType dataRefType;

//    CFStringRef URLString = CFStringCreateWithCString
 //       (0, m_path.toLocal8Bit().data(), 0);


    QByteArray ba = m_path.toLocal8Bit();

    CFURLRef url = CFURLCreateFromFileSystemRepresentation
        (kCFAllocatorDefault,
         (const UInt8 *)ba.data(),
         (CFIndex)ba.length(),
         false);


//    m_d->err = QTNewDataReferenceFromURLCFString
    m_d->err = QTNewDataReferenceFromCFURL
        (url, 0, &dataRef, &dataRefType);

    if (m_d->err) { 
        m_error = QString("Error creating data reference for QuickTime decoder: code %1").arg(m_d->err);
        return;
    }
    
    short fileID = movieInDataForkResID; 
    short flags = 0; 
    m_d->err = NewMovieFromDataRef
        (&m_d->movie, flags, &fileID, dataRef, dataRefType);

    DisposeHandle(dataRef);
    if (m_d->err) { 
        m_error = QString("Error creating new movie for QuickTime decoder: code %1").arg(m_d->err); 
        return;
    }

    Boolean isProtected = 0;
    Track aTrack = GetMovieIndTrackType
        (m_d->movie, 1, SoundMediaType,
         movieTrackMediaType | movieTrackEnabledOnly);

    if (aTrack) {
        Media aMedia = GetTrackMedia(aTrack);	// get the track media
        if (aMedia) {
            MediaHandler mh = GetMediaHandler(aMedia);	// get the media handler we can query
            if (mh) {
                m_d->err = QTGetComponentProperty(mh,
                                                  kQTPropertyClass_DRM,
                                                  kQTDRMPropertyID_IsProtected,
                                                  sizeof(Boolean), &isProtected,nil);
            } else {
                m_d->err = 1;
            }
        } else {
            m_d->err = 1;
        }
    } else {
        m_d->err = 1;
    }
	
    if (m_d->err && m_d->err != kQTPropertyNotSupportedErr) { 
        m_error = QString("Error checking for DRM in QuickTime decoder: code %1").arg(m_d->err);
        return;
    } else if (!m_d->err && isProtected) { 
        m_error = QString("File is protected with DRM");
        return;
    } else if (m_d->err == kQTPropertyNotSupportedErr && !isProtected) {
        std::cerr << "QuickTime: File is not protected with DRM" << std::endl;
    }

    if (m_d->movie) {
        SetMovieActive(m_d->movie, TRUE);
        m_d->err = GetMoviesError();
        if (m_d->err) {
            m_error = QString("Error in QuickTime decoder activation: code %1").arg(m_d->err);
            return;
        }
    } else {
	m_error = QString("Error in QuickTime decoder: Movie object not valid");
	return;
    }
    
    m_d->err = MovieAudioExtractionBegin
        (m_d->movie, 0, &m_d->extractionSessionRef);
    if (m_d->err) {
        m_error = QString("Error in QuickTime decoder extraction init: code %1").arg(m_d->err);
        return;
    }

    m_d->err = MovieAudioExtractionGetProperty
        (m_d->extractionSessionRef,
         kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
         sizeof(m_d->asbd),
         &m_d->asbd,
         nil);

    if (m_d->err) {
        m_error = QString("Error in QuickTime decoder property get: code %1").arg(m_d->err);
        return;
    }
	
    m_channelCount = m_d->asbd.mChannelsPerFrame;
    m_fileRate = m_d->asbd.mSampleRate;

    std::cerr << "QuickTime: " << m_channelCount << " channels, " << m_fileRate << " kHz" << std::endl;

    m_d->asbd.mFormatFlags =
        kAudioFormatFlagIsFloat |
        kAudioFormatFlagIsPacked |
        kAudioFormatFlagsNativeEndian;
    m_d->asbd.mBitsPerChannel = sizeof(float) * 8;
    m_d->asbd.mBytesPerFrame = sizeof(float) * m_d->asbd.mChannelsPerFrame;
    m_d->asbd.mBytesPerPacket = m_d->asbd.mBytesPerFrame;
	
    m_d->err = MovieAudioExtractionSetProperty
        (m_d->extractionSessionRef,
         kQTPropertyClass_MovieAudioExtraction_Audio,
         kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
         sizeof(m_d->asbd),
         &m_d->asbd);

    if (m_d->err) {
        m_error = QString("Error in QuickTime decoder property set: code %1").arg(m_d->err);
        m_channelCount = 0;
        return;
    }
    m_d->buffer.mNumberBuffers = 1;
    m_d->buffer.mBuffers[0].mNumberChannels = m_channelCount;
    m_d->buffer.mBuffers[0].mDataByteSize =
        sizeof(float) * m_channelCount * m_d->blockSize;
    m_d->data = new float[m_channelCount * m_d->blockSize];
    m_d->buffer.mBuffers[0].mData = m_d->data;

    initialiseDecodeCache();

    if (decodeMode == DecodeAtOnce) {

        if (m_reporter) {
            connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled()));
            m_reporter->setMessage
                (tr("Decoding %1...").arg(QFileInfo(m_path).fileName()));
        }

        while (1) {
            
            UInt32 framesRead = m_d->blockSize;
            UInt32 extractionFlags = 0;
            m_d->err = MovieAudioExtractionFillBuffer
                (m_d->extractionSessionRef, &framesRead, &m_d->buffer,
                 &extractionFlags);
            if (m_d->err) {
                m_error = QString("Error in QuickTime decoding: code %1")
                    .arg(m_d->err);
                break;
            }

            //!!! progress?

//    std::cerr << "Read " << framesRead << " frames (block size " << m_d->blockSize << ")" << std::endl;

            // QuickTime buffers are interleaved unless specified otherwise
            addSamplesToDecodeCache(m_d->data, framesRead);

            if (framesRead < m_d->blockSize) break;
        }
        
        finishDecodeCache();
        endSerialised();

        m_d->err = MovieAudioExtractionEnd(m_d->extractionSessionRef);
        if (m_d->err) {
            m_error = QString("Error ending QuickTime extraction session: code %1").arg(m_d->err);
        }

        m_completion = 100;

    } else {
        if (m_reporter) m_reporter->setProgress(100);

        if (m_channelCount > 0) {
            m_decodeThread = new DecodeThread(this);
            m_decodeThread->start();
        }
    }

    std::cerr << "QuickTimeFileReader::QuickTimeFileReader: frame count is now " << getFrameCount() << ", error is \"\"" << m_error << "\"" << std::endl;
}
コード例 #4
0
ComponentResult write_vorbisPrivateData(GenericStreamPtr as, UInt8 **buf, UInt32 *bufSize)
{
  ComponentResult err = noErr;
  void *magicCookie = NULL;
  UInt32 cookieSize = 0;
  dbg_printf("[WebM] Get Vorbis Private Data\n");

  err = QTGetComponentPropertyInfo(as->aud.vorbisComponentInstance,
                                   kQTPropertyClass_SCAudio,
                                   kQTSCAudioPropertyID_MagicCookie,
                                   NULL, &cookieSize, NULL);

  if (err) return err;

  dbg_printf("[WebM] Cookie Size %d\n", cookieSize);

  magicCookie = calloc(1, cookieSize);
  err = QTGetComponentProperty(as->aud.vorbisComponentInstance,
                               kQTPropertyClass_SCAudio,
                               kQTSCAudioPropertyID_MagicCookie,
                               cookieSize, magicCookie, NULL);

  if (err) goto bail;

  UInt8 *ptrheader = (UInt8 *) magicCookie;
  UInt8 *cend = ptrheader + cookieSize;
  CookieAtomHeader *aheader = (CookieAtomHeader *) ptrheader;
  WebMBuffer header, header_vc, header_cb;
  header.size = header_vc.size = header_cb.size = 0;

  while (ptrheader < cend)
  {
    aheader = (CookieAtomHeader *) ptrheader;
    ptrheader += EndianU32_BtoN(aheader->size);

    if (ptrheader > cend || EndianU32_BtoN(aheader->size) <= 0)
      break;

    switch (EndianS32_BtoN(aheader->type))
    {
      case kCookieTypeVorbisHeader:
        header.size = EndianS32_BtoN(aheader->size) - 2 * sizeof(long);
        header.data = aheader->data;
        break;

      case kCookieTypeVorbisComments:
        header_vc.size = EndianS32_BtoN(aheader->size) - 2 * sizeof(long);
        header_vc.data = aheader->data;
        break;

      case kCookieTypeVorbisCodebooks:
        header_cb.size = EndianS32_BtoN(aheader->size) - 2 * sizeof(long);
        header_cb.data = aheader->data;
        break;

      default:
        break;
    }
  }

  if (header.size == 0 || header_vc.size == 0 || header_cb.size == 0)
  {
    err = paramErr;
    goto bail;
  }

  //1 + header1 /255 + header2 /255 + idheader.len +
  *bufSize = 1;  //the first byte which is always 0x02
  *bufSize += (header.size - 1) / 255 + 1; //the header size lacing
  *bufSize += (header_vc.size - 1) / 255 + 1; //the comment size lacing
  *bufSize += header.size + header_vc.size + header_cb.size; //the packets
  dbg_printf("[WebM]Packet headers  %d %d %d -- total buffer %d\n",
             header.size, header_vc.size , header_cb.size, *bufSize);
  *buf = malloc(*bufSize);
  UInt8 *ptr = *buf;

  *ptr = 0x02;
  ptr ++;
  //using ogg lacing write out the size of the first two packets
  _oggLacing(&ptr, header.size);
  _oggLacing(&ptr, header_vc.size);

  _dbg_printVorbisHeader(header.data);

  memcpy(ptr, header.data, header.size);
  ptr += header.size;
  memcpy(ptr, header_vc.data, header_vc.size);
  ptr += header_vc.size;
  memcpy(ptr, header_cb.data, header_cb.size);

bail:

  if (magicCookie != NULL)
  {
    free(magicCookie);
    magicCookie = NULL;
  }

  return err;
}