static void _MetadataCallback(void* aAppleATDecoder, AudioFileStreamID aStream, AudioFileStreamPropertyID aProperty, UInt32* aFlags) { AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aAppleATDecoder); LOG("MetadataCallback receiving: '%s'", FourCC2Str(aProperty)); if (aProperty == kAudioFileStreamProperty_MagicCookieData) { UInt32 size; Boolean writeable; OSStatus rv = AudioFileStreamGetPropertyInfo(aStream, aProperty, &size, &writeable); if (rv) { LOG("Couldn't get property info for '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } nsAutoArrayPtr<uint8_t> data(new uint8_t[size]); rv = AudioFileStreamGetProperty(aStream, aProperty, &size, data); if (rv) { LOG("Couldn't get property '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } decoder->mMagicCookie.AppendElements(data.get(), size); } }
INT32 PORT_GetPortType(void* id, INT32 portIndex) { PortMixer *mixer = (PortMixer *)id; INT32 ret = 0; if (portIndex < 0 || portIndex >= mixer->portCount) { ERROR1("PORT_GetPortType: line (portIndex = %d) not found\n", portIndex); return 0; } AudioObjectPropertyScope scope = mixer->ports[portIndex].scope; AudioStreamID streamID = mixer->ports[portIndex].streamID; if (streamID != 0) { UInt32 terminalType; OSStatus err = GetAudioObjectProperty(streamID, kAudioObjectPropertyScopeGlobal, kAudioStreamPropertyTerminalType, sizeof(terminalType), &terminalType, 1); if (err) { OS_ERROR1(err, "PORT_GetPortType(kAudioStreamPropertyTerminalType), portIndex=%d", portIndex); return 0; } // Note that kAudioStreamPropertyTerminalType actually returns values from // IOAudioTypes.h, not the defined kAudioStreamTerminalType*. TRACE4("PORT_GetPortType (portIndex=%d), scope=%s, termType=0x%04x (%s)\n", (int)portIndex, FourCC2Str(scope), (int)terminalType, FourCC2Str(terminalType)); switch (terminalType) { case INPUT_MICROPHONE: ret = PORT_SRC_MICROPHONE; break; case OUTPUT_SPEAKER: ret = PORT_DST_SPEAKER; break; case OUTPUT_HEADPHONES: ret = PORT_DST_HEADPHONE; break; case EXTERNAL_LINE_CONNECTOR: ret = scope == kAudioDevicePropertyScopeInput ? PORT_SRC_LINE_IN : PORT_DST_LINE_OUT; break; default: TRACE1(" unknown output terminal type %#x\n", terminalType); } } else { TRACE0(" PORT_GetPortType: multiple streams\n"); } if (ret == 0) { // if the type not detected, return "common type" ret = scope == kAudioDevicePropertyScopeInput ? PORT_SRC_UNKNOWN : PORT_DST_UNKNOWN; } TRACE2("<<PORT_GetPortType (portIndex=%d) = %d\n", portIndex, ret); return ret; }
static void _MetadataCallback(void* aAppleATDecoder, AudioFileStreamID aStream, AudioFileStreamPropertyID aProperty, UInt32* aFlags) { AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aAppleATDecoder); MOZ_RELEASE_ASSERT(decoder->mTaskQueue->IsCurrentThreadIn()); LOGEX(decoder, "MetadataCallback receiving: '%s'", FourCC2Str(aProperty)); if (aProperty == kAudioFileStreamProperty_MagicCookieData) { UInt32 size; Boolean writeable; OSStatus rv = AudioFileStreamGetPropertyInfo(aStream, aProperty, &size, &writeable); if (rv) { LOGEX(decoder, "Couldn't get property info for '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } auto data = MakeUnique<uint8_t[]>(size); rv = AudioFileStreamGetProperty(aStream, aProperty, &size, data.get()); if (rv) { LOGEX(decoder, "Couldn't get property '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } decoder->mMagicCookie.AppendElements(data.get(), size); } }
void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { PortMixer *mixer = (PortMixer *)id; TRACE1(">>PORT_GetControls (portIndex = %d)\n", portIndex); if (portIndex < 0 || portIndex >= mixer->portCount) { ERROR1("<<PORT_GetControls: line (portIndex = %d) not found\n", portIndex); return; } PortLine *port = &(mixer->ports[portIndex]); if (mixer->deviceControlCount < 0) { // not initialized OSStatus err; UInt32 size; // deviceControlCount is overestimated // because we don't actually filter by if the owned objects are controls err = GetAudioObjectPropertySize(mixer->deviceID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyOwnedObjects, &size); if (err) { OS_ERROR1(err, "PORT_GetControls (portIndex = %d) get OwnedObject size", portIndex); } else { mixer->deviceControlCount = size / sizeof(AudioObjectID); TRACE1(" PORT_GetControls: detected %d owned objects\n", mixer->deviceControlCount); AudioObjectID controlIDs[mixer->deviceControlCount]; err = GetAudioObjectProperty(mixer->deviceID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyOwnedObjects, sizeof(controlIDs), controlIDs, 1); if (err) { OS_ERROR1(err, "PORT_GetControls (portIndex = %d) get OwnedObject values", portIndex); } else { mixer->deviceControls = (AudioControl *)calloc(mixer->deviceControlCount, sizeof(AudioControl)); for (int i = 0; i < mixer->deviceControlCount; i++) { AudioControl *control = &mixer->deviceControls[i]; control->controlID = controlIDs[i]; OSStatus err1 = GetAudioObjectProperty(control->controlID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyClass, sizeof(control->classID), &control->classID, 1); OSStatus err2 = GetAudioObjectProperty(control->controlID, kAudioObjectPropertyScopeGlobal, kAudioControlPropertyScope, sizeof(control->scope), &control->scope, 1); OSStatus err3 = GetAudioObjectProperty(control->controlID, kAudioObjectPropertyScopeGlobal, kAudioControlPropertyElement, sizeof(control->channel), &control->channel, 1); if (err1 || err2 || err3) { // not a control or other error control->classID = 0; continue; } TRACE4("- control 0x%x, class='%s', scope='%s', channel=%d\n", control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel); } } } } if (mixer->deviceControlCount <= 0) { TRACE1("<<PORT_GetControls (portIndex = %d): no owned AudioControls\n", portIndex); return; } int totalChannels = GetChannelCount(mixer->deviceID, port->scope == kAudioDevicePropertyScopeOutput ? 1 : 0); // collect volume and mute controls AudioControl* volumeControls[totalChannels+1]; // 0 - for master channel memset(&volumeControls, 0, sizeof(AudioControl *) * (totalChannels+1)); AudioControl* muteControls[totalChannels+1]; // 0 - for master channel memset(&muteControls, 0, sizeof(AudioControl *) * (totalChannels+1)); for (int i=0; i<mixer->deviceControlCount; i++) { AudioControl *control = &mixer->deviceControls[i]; if (control->classID == 0 || control->scope != port->scope || control->channel > (unsigned)totalChannels) { continue; } if (control->classID == kAudioVolumeControlClassID) { if (volumeControls[control->channel] == NULL) { volumeControls[control->channel] = control; } else { ERROR4("WARNING: duplicate VOLUME control 0x%x, class='%s', scope='%s', channel=%d\n", control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel); } } else if (control->classID == kAudioMuteControlClassID) { if (muteControls[control->channel] == NULL) { muteControls[control->channel] = control; } else { ERROR4("WARNING: duplicate MUTE control 0x%x, class='%s', scope='%s', channel=%d\n", control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel); } } else { #ifdef USE_ERROR if (control->classID != 0) { ERROR4("WARNING: unhandled control 0x%x, class='%s', scope='%s', channel=%d\n", control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel); } #endif } } //////////////////////////////////////////////////////// // create java control hierarchy void *masterVolume = NULL, *masterMute = NULL, *masterBalance = NULL; // volumeControls[0] and muteControls[0] - master volume/mute // volumeControls[n] and muteControls[n] (n=1..totalChannels) - corresponding channel controls if (volumeControls[0] != NULL) { // "master volume" AudioControl masterVolume = CreatePortControl(mixer, creator, PortControl::Volume, volumeControls, 0, 1); } else { if (ValidControlCount(volumeControls, 1, totalChannels) == totalChannels) { // every channel has volume control => create virtual master volume masterVolume = CreatePortControl(mixer, creator, PortControl::Volume, volumeControls, 1, totalChannels); } else { TRACE2(" PORT_GetControls (master volume): totalChannels = %d, valid volume controls = %d\n", totalChannels, ValidControlCount(volumeControls, 1, totalChannels)); } } if (muteControls[0] != NULL) { // "master mute" masterMute = CreatePortControl(mixer, creator, PortControl::Mute, muteControls, 0, 1); } else { if (ValidControlCount(muteControls, 1, totalChannels) == totalChannels) { // every channel has mute control => create virtual master mute control masterMute = CreatePortControl(mixer, creator, PortControl::Mute, muteControls, 1, totalChannels); } else { TRACE2(" PORT_GetControls (master mute): totalChannels = %d, valid volume controls = %d\n", totalChannels, ValidControlCount(muteControls, 1, totalChannels)); } } // virtual balance if (totalChannels == 2) { if (ValidControlCount(volumeControls, 1, totalChannels) == totalChannels) { masterBalance = CreatePortControl(mixer, creator, PortControl::Balance, volumeControls, 1, totalChannels); } else { TRACE2(" PORT_GetControls (naster balance): totalChannels = %d, valid volume controls = %d\n", totalChannels, ValidControlCount(volumeControls, 1, totalChannels)); } } // add "master" controls if (masterVolume != NULL) { creator->addControl(creator, masterVolume); } if (masterBalance != NULL) { creator->addControl(creator, masterBalance); } if (masterMute != NULL) { creator->addControl(creator, masterMute); } // don't add per-channel controls for mono & stereo - they are handled by "master" controls // TODO: this should be reviewed to handle controls other than mute & volume if (totalChannels > 2) { // add separate compound control for each channel (containing volume and mute) // (ensure that we have controls) if (ValidControlCount(volumeControls, 1, totalChannels) > 0 || ValidControlCount(muteControls, 1, totalChannels) > 0) { for (int ch=1; ch<=totalChannels; ch++) { // get the channel name char *channelName; CFStringRef cfname = NULL; const AudioObjectPropertyAddress address = {kAudioObjectPropertyElementName, port->scope, ch}; UInt32 size = sizeof(cfname); OSStatus err = AudioObjectGetPropertyData(mixer->deviceID, &address, 0, NULL, &size, &cfname); if (err == noErr) { CFIndex length = CFStringGetLength(cfname) + 1; channelName = (char *)malloc(length); CFStringGetCString(cfname, channelName, length, kCFStringEncodingUTF8); CFRelease(cfname); } else { channelName = (char *)malloc(16); sprintf(channelName, "Ch %d", ch); } void* jControls[2]; int controlCount = 0; if (volumeControls[ch] != NULL) { jControls[controlCount++] = CreatePortControl(mixer, creator, PortControl::Volume, volumeControls, ch, 1); } if (muteControls[ch] != NULL) { jControls[controlCount++] = CreatePortControl(mixer, creator, PortControl::Mute, muteControls, ch, 1); } // TODO: add any extra controls for "other" controls for the channel void *compoundControl = creator->newCompoundControl(creator, channelName, jControls, controlCount); creator->addControl(creator, compoundControl); free(channelName); } } } AddChangeListeners(mixer); TRACE1("<<PORT_GetControls (portIndex = %d)\n", portIndex); }
HRESULT CAviBitmap::Init() { HRESULT hr = E_FAIL; do { //Open file hr = AVIFileOpen(&m_pAviFile, m_szFileName, OF_READ, NULL); if(hr != S_OK) { m_szLastErrorMsg.Format(_T("Unable to Open the Movie File")); break; } //Get video stream hr = AVIFileGetStream(m_pAviFile, &m_pAviStream, streamtypeVIDEO /*video stream*/, 0 /*first stream*/); if(hr != S_OK) { m_szLastErrorMsg.Format(_T("Unable to Get the video stream")); break; } hr = AVIStreamInfo(m_pAviStream, &m_aviInfo, sizeof(AVISTREAMINFO)); if(hr != S_OK) { m_szLastErrorMsg.Format(_T("Unable to Get the video stream info")); break; } CString szFourCC; FourCC2Str(m_aviInfo.fccHandler, szFourCC); AfxTrace(_T("fccHandler=%s, 0x%08X\n"), szFourCC, m_aviInfo.fccHandler); ZeroMemory(&m_biWanted, sizeof(m_biWanted)); LONG lFormat = sizeof(m_biWanted); hr = AVIStreamReadFormat(m_pAviStream, 0, &m_biWanted, &lFormat); if(hr != S_OK) { m_szLastErrorMsg.Format(_T("Unable to Get the foramt of the 1st frame")); break; } m_biWanted.biCompression = BI_RGB; m_biWanted.biBitCount = 32; m_biWanted.biSizeImage = m_biWanted.biWidth * 4 * m_biWanted.biHeight; //Set the result to Fail hr = E_FAIL; //Get the GETFRAME handle m_pGetFrame = AVIStreamGetFrameOpen(m_pAviStream, &m_biWanted); if(m_pGetFrame == NULL) { m_szLastErrorMsg.Format(_T("Unable to Get the GETFRAME handle")); break; } //Get the 1st sample m_lFirstSample = AVIStreamStart(m_pAviStream); if(m_lFirstSample == -1) { m_szLastErrorMsg.Format(_T("Unable to Get the first sample")); break; } //Get the total sample count m_lSampleCount = AVIStreamLength(m_pAviStream); if(m_lSampleCount == -1) { m_szLastErrorMsg.Format(_T("Unable to Get the sample count")); break; } //Done hr = S_OK; } while (FALSE); if(hr != S_OK) { ReleaseMemory(); } return hr; }
HRESULT CAviBitmap::GetAllFrames(LPCTSTR lpszFolderName) { if(m_pGetFrame == NULL) { m_szLastErrorMsg.Format(_T("Not initialized yet")); return E_FAIL; } HRESULT hr = S_OK; int nBmpInfoHdrSize = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256; BITMAPINFOHEADER* lpBmpInfoHdr = (BITMAPINFOHEADER*)(new BYTE[nBmpInfoHdrSize]); LONG lpcbFormat = nBmpInfoHdrSize; BYTE* lpDib = NULL; BYTE* lpBuffer = NULL; LONG lBytes = 0, lSamples = 0; BOOL bReadRaw = FALSE; int nPos = 0; int nSampleCount = min(m_lSampleCount, 101); for(nPos = 0; nPos < nSampleCount; nPos++) { //Get the frame format hr = AVIStreamReadFormat(m_pAviStream, nPos, lpBmpInfoHdr, &lpcbFormat); if(hr != S_OK) { m_szLastErrorMsg.Format(_T("Unable to Get the sample format: %d"), nPos); break; } lpBuffer = NULL; //Try to read raw data when the bitmap is BI_RGB if(lpBmpInfoHdr->biCompression == BI_RGB && (lpBmpInfoHdr->biBitCount == 24 || lpBmpInfoHdr->biBitCount == 32)) { //Get the frame data lpBuffer = new BYTE[m_biWanted.biSizeImage]; hr = AVIStreamRead(m_pAviStream, nPos, 1, lpBuffer, m_biWanted.biSizeImage, &lBytes, &lSamples); if(hr != S_OK) { m_szLastErrorMsg.Format(_T("Unable to Get the sample data: %d"), nPos); break; } } else { CString szFourCC; FourCC2Str(m_aviInfo.fccHandler, szFourCC); AfxTrace(_T("Non-RGB format at frame(%03d)=%s, 0x%08X\n"), nPos, szFourCC, lpBmpInfoHdr->biCompression); } //Get the frame at nPos lpDib = (BYTE*)AVIStreamGetFrame(m_pGetFrame, nPos); if(lpDib == NULL) { m_szLastErrorMsg.Format(_T("Unable to Get the sample: %d"), nPos); hr = E_FAIL; break; } //compare the data retrieved in 2 ways if needed if(lpBuffer != NULL) { if(memcmp(lpBuffer, lpDib + sizeof(BITMAPINFOHEADER), lpBmpInfoHdr->biSizeImage) != 0) { m_szLastErrorMsg.Format(_T("not equals: %d"), nPos); hr = E_FAIL; break; } } CString szFileName; if(lpszFolderName == NULL) { szFileName.Format(_T(".\\Frame%03d.bmp"), nPos); } else { szFileName.Format(_T("%s\\Frame%03d.bmp"), lpszFolderName, nPos); } BITMAPINFOHEADER* pTemp = (BITMAPINFOHEADER*)lpDib; // hr = SaveBitmap(lpBmpInfoHdr, lpBuffer, lpBmpInfoHdr->biSizeImage, szFileName); hr = SaveBitmap(&m_biWanted, lpDib + sizeof(BITMAPINFOHEADER), m_biWanted.biSizeImage, szFileName); if(lpBuffer != NULL) { delete [] lpBuffer; lpBuffer = NULL; } //Done } if(lpBuffer != NULL) { delete [] lpBuffer; lpBuffer = NULL; } if(lpBmpInfoHdr != NULL) { delete [] lpBmpInfoHdr; lpBmpInfoHdr = NULL; } ReleaseMemory(); return hr; }
// Will set mChannelLayout if a channel layout could properly be identified // and is supported. nsresult AppleATDecoder::SetupChannelLayout() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); // Determine the channel layout. UInt32 propertySize; UInt32 size; OSStatus status = AudioConverterGetPropertyInfo(mConverter, kAudioConverterOutputChannelLayout, &propertySize, NULL); if (status || !propertySize) { LOG("Couldn't get channel layout property (%s)", FourCC2Str(status)); return NS_ERROR_FAILURE; } auto data = MakeUnique<uint8_t[]>(propertySize); size = propertySize; status = AudioConverterGetProperty(mConverter, kAudioConverterInputChannelLayout, &size, data.get()); if (status || size != propertySize) { LOG("Couldn't get channel layout property (%s)", FourCC2Str(status)); return NS_ERROR_FAILURE; } AudioChannelLayout* layout = reinterpret_cast<AudioChannelLayout*>(data.get()); AudioChannelLayoutTag tag = layout->mChannelLayoutTag; // if tag is kAudioChannelLayoutTag_UseChannelDescriptions then the structure // directly contains the the channel layout mapping. // If tag is kAudioChannelLayoutTag_UseChannelBitmap then the layout will // be defined via the bitmap and can be retrieved using // kAudioFormatProperty_ChannelLayoutForBitmap property. // Otherwise the tag itself describes the layout. if (tag != kAudioChannelLayoutTag_UseChannelDescriptions) { AudioFormatPropertyID property = tag == kAudioChannelLayoutTag_UseChannelBitmap ? kAudioFormatProperty_ChannelLayoutForBitmap : kAudioFormatProperty_ChannelLayoutForTag; if (property == kAudioFormatProperty_ChannelLayoutForBitmap) { status = AudioFormatGetPropertyInfo(property, sizeof(UInt32), &layout->mChannelBitmap, &propertySize); } else { status = AudioFormatGetPropertyInfo(property, sizeof(AudioChannelLayoutTag), &tag, &propertySize); } if (status || !propertySize) { LOG("Couldn't get channel layout property info (%s:%s)", FourCC2Str(property), FourCC2Str(status)); return NS_ERROR_FAILURE; } data = MakeUnique<uint8_t[]>(propertySize); layout = reinterpret_cast<AudioChannelLayout*>(data.get()); size = propertySize; if (property == kAudioFormatProperty_ChannelLayoutForBitmap) { status = AudioFormatGetProperty(property, sizeof(UInt32), &layout->mChannelBitmap, &size, layout); } else { status = AudioFormatGetProperty(property, sizeof(AudioChannelLayoutTag), &tag, &size, layout); } if (status || size != propertySize) { LOG("Couldn't get channel layout property (%s:%s)", FourCC2Str(property), FourCC2Str(status)); return NS_ERROR_FAILURE; } // We have retrieved the channel layout from the tag or bitmap. // We can now directly use the channel descriptions. layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; } if (layout->mNumberChannelDescriptions > MAX_AUDIO_CHANNELS || layout->mNumberChannelDescriptions != mOutputFormat.mChannelsPerFrame) { LOG("Nonsensical channel layout or not matching the original channel number"); return NS_ERROR_FAILURE; } AudioConfig::Channel channels[MAX_AUDIO_CHANNELS]; for (uint32_t i = 0; i < layout->mNumberChannelDescriptions; i++) { AudioChannelLabel id = layout->mChannelDescriptions[i].mChannelLabel; AudioConfig::Channel channel = ConvertChannelLabel(id); channels[i] = channel; } mChannelLayout = MakeUnique<AudioConfig::ChannelLayout>(mOutputFormat.mChannelsPerFrame, channels); return NS_OK; }