WMAERR WMA_LoadHeaderObject(tWMAFileHdrStateInternal *pInt, int isFull) { GUID objectId; QWORD qwSize; DWORD cHeaders; BYTE align; BYTE arch; BYTE *pData; DWORD cbWanted; DWORD cbActual; // char *cmp_p1,*cmp_p2; if(pInt == NULL) { return WMAERR_INVALIDARG; } cbWanted = MIN_OBJECT_SIZE + sizeof(DWORD) + 2*sizeof(BYTE); cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } pInt->currPacketOffset += cbActual; LoadGUID(objectId, pData); LoadQWORD(qwSize, pData); LoadDWORD(cHeaders, pData); LoadBYTE(align, pData); LoadBYTE(arch, pData); if(!WMA_IsEqualGUID(&objectId, &CLSID_CAsfHeaderObjectV0)|| align != 1|| arch != 2) { return WMAERR_INVALIDHEADER; } pInt->cbHeader = qwSize.dwLo; return WMAERR_OK; }
void _CRTAPI1 main( int ArgC, char *ArgS[] ) { HANDLE handle; ULONG bytesRead; ULONG lsn; int i; int j; int lines; char c; char lastCmd; char currentDrive[12]; PPTE partitionTable; BOOLEAN modify = FALSE; BOOLEAN more = FALSE; // Disable hard-error popups. SetErrorMode(TRUE); // See if we are connected to CON Batch = (BOOLEAN)(!isatty(0)); switch (ArgC) { case 2: // Nothing to do for level 2 break; case 3: if (strcmp(_strupr(ArgS[2]), "/E") == 0) { modify = TRUE; fprintf(stderr, "Warning: Opening drive %s for write access!\n", ArgS[1]); break; } else { fprintf(stderr, "%s: Invalid option '%s'\n", ArgS[0], ArgS[2]); } // Note fall through to default: (usage case) default: if (ArgC > 3) fprintf(stderr, "%s: Too many arguments\n", ArgS[0]); fprintf(stderr, "usage: %s diskno [/e]\n", ArgS[0]); // Re-enable harderror popups. SetErrorMode(FALSE); exit(-1); break; } sprintf(currentDrive, "%s", ArgS[1]); if (!OpenFile(currentDrive, &handle)) { fprintf(stderr, "%s: Unable to open %s\n", ArgS[0], currentDrive); // Re-enable harderror popups. SetErrorMode(FALSE); exit(1); } // check if we want to do writes with dasd if (modify) { // This is a drive, and we want to modify it, so we need // to lock it. if (!LockVolume(handle)) { printf("Unable to lock volume.\n"); // Re-enable harderror popups. SetErrorMode(FALSE); exit(1); } } // default to sector 0 lsn = 0; while (1) { PromptUsr(); if (fgets(Command, sizeof(Command), stdin) == NULL) break; if ((i = sscanf(Command, "%c %li", &c, &lsn)) > 1) { if ((c != 'c') && (c != 'C')) { /* * The user entered a lsn as well as an lsn based command, * convert it to byte seek pos */ lsn *= SECSIZE; } } more = FALSE; c = (char)tolower((int)c); // pre process command if (c == 'q') break; if (c == '\n') c = lastCmd; switch (c) { case 'b': if (i == 1 && lastCmd == c) { // same command with no new lsn, use the next one on disk lsn -= bytesRead; } break; case 'c': // change drives. if (i != 2) { fprintf(stderr, "You must specify a drive number to change drives.\n"); continue; } CloseFile(handle); sprintf(currentDrive, "%d", lsn); if (!OpenFile(currentDrive, &handle)) { fprintf(stderr, "%s: Unable to open %s\n", ArgS[0], currentDrive); // Re-enable harderror popups. SetErrorMode(FALSE); exit(1); } // check if we want to do writes with dasd if (modify) { // This is a drive, and we want to modify it, so we need // to lock it. if (!LockVolume(handle)) { printf("Unable to lock volume.\n"); // Re-enable harderror popups. SetErrorMode(FALSE); exit(1); } } // default to sector 0 lsn = 0; continue; case 'g': { DISK_GEOMETRY diskGeometry; IO_STATUS_BLOCK statusBlock; NTSTATUS status; // Get and display drive geometry from system. status = NtDeviceIoControlFile(handle, 0, NULL, NULL, &statusBlock, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &diskGeometry, sizeof(DISK_GEOMETRY)); if (NT_SUCCESS(status)) { printf("BytesPerSector: %d\n", diskGeometry.BytesPerSector); printf("SectorsPerTrack: %d\n", diskGeometry.SectorsPerTrack); printf("TracksPerCylinder: %d\n", diskGeometry.TracksPerCylinder); printf("NumberOfCylinders: %d\n", diskGeometry.Cylinders); } else { fprintf(stderr, "Could not get geometry %x\n", status); } continue; } case 'm': case 'd': case 'e': case 'p': if (i == 1 && lastCmd == c) { // same command with no new lsn, use the next one on disk lsn += bytesRead; } break; default: fprintf(stderr,"Unknown command '%c'\n", c); case 'h': case '?': fprintf(stderr," d [####]\tDump sector ####\n"); fprintf(stderr," e [####]\tEdit sector ####\n"); fprintf(stderr," m [####]\tDump sector with 'MORE'\n"); fprintf(stderr," b [####]\tSame as 'd' but defaults to" " previous sector\n"); fprintf(stderr," c [##]\tChange harddisk number\n"); fprintf(stderr," p [####]\tDump partition table on sector ###\n"); fprintf(stderr," q \tquit the program"); fprintf(stderr,"\n" "\n If no new sector is given and the command is the same, the next" "\n sector on the disk is used. If no sector is given but the command" "\n is different from the previous command, the sector used in the" "\n last command will be used again.\n" ); continue; } // remember last command lastCmd = c; bytesRead = 0; if(!ReadSector(handle, lsn, Sector, &bytesRead)) { printf("Unable to read sector %lx\n", lsn); } else { printf("\n lsn:0x%lX bytes read:%d\n", lsn / SECSIZE, bytesRead); switch (c) { case 'm': /* * More */ more = TRUE; // fall through to Dump case 'd': case 'b': /* * Dump */ lines = 0; HexLine[0] = '\0'; CharLine[0] = '\0'; i = 0; sprintf(HexLine, "%04X ", i); for (i = 0; i < (int)bytesRead; i++) { sprintf(HexLine, "%s%2x ", HexLine, Sector[i]); sprintf(CharLine, "%s%c", CharLine, (isprint(Sector[i])) ? Sector[i] : '.'); if ((i != 0) && ((i % 16) == 15)) { printf("%s *%s*\n", HexLine, CharLine); HexLine[0] = '\0'; sprintf(HexLine, "%04X ", i + 1); CharLine[0] = '\0'; lines++; } if (more && (lines == 20)) { printf("\n--MORE--"); MyGetChr(); printf("\r"); lines = 0; } } putchar('\n'); break; case 'p': /* * dump partition table */ if (LoadWORD(&Sector[SIGNATURE_OFFSET]) == 0xaa55) { partitionTable = ((PBOOTSECTOR)Sector)->PartitionTable; for (i = 0; i < 4; i++) { printf("\nEntry #%u:\n",i); printf(" Boot flag : %u\n", partitionTable[i].BootIndicator); printf(" System ID : %u\n", partitionTable[i].SysID); printf(" Relative sectors: %u (0x%x)\n", LoadDWORD(&partitionTable[i].Relative0), LoadDWORD(&partitionTable[i].Relative0)); printf(" Sector count : %u (0x%x) [%u MB]\n", LoadDWORD(&partitionTable[i].SectorCount0), LoadDWORD(&partitionTable[i].SectorCount0), (LoadDWORD(&partitionTable[i].SectorCount0) * SECSIZE) / (1024*1024)); printf(" Start CHS : %u %u %u\n", partitionTable[i].StartCylinder | ((partitionTable[i].StartSector & 0xc0) << 2), partitionTable[i].StartHead, partitionTable[i].StartSector & 0x3f); printf(" End CHS : %u %u %u\n", partitionTable[i].EndCylinder | ((partitionTable[i].EndSector & 0xc0) << 2), partitionTable[i].EndHead, partitionTable[i].EndSector & 0x3f); } } else { printf("\nSector %u is not a valid master boot sector.\n", lsn/SECSIZE); } break; case 'e': /* * Edit */ if (!modify) { printf("Can not edit, restart with /e option\n"); } else { for (i = 0; i < (int)bytesRead; i++) { if ((i % CB_INPUTLINE) == 0) { // print line header printf("\n%04X\t", i); } printf("%02X.", (BYTE)Sector[i]); if (MyGetInput(&j, &c )) { Sector[i] = (BYTE)j; } else { printf("%02X", (BYTE)Sector[i]); } if (c == '\r') break; putchar('\t'); } printf("\nWrite new data to sector? (Y/N)"); c = (char)MyGetChr(); if ((c = (char)toupper(c)) == 'Y') { // User wants to save the data printf("Yes...."); if (!WriteSector(handle, lsn, Sector)) { fprintf(stderr, "Write failed\n"); } else { // indicate success printf("\t[Done]\n"); } } else { // user chickened out printf("No....\t[Nothing written]\n"); } } break; } } } // if this was a dasd open, then unlock the drive if (modify) { UnlockVolume(handle); } CloseFile(handle); // Re-enable harderror popups. SetErrorMode(FALSE); exit(0); }
// This routine parses the wma config header and returns Sampling Rate, Number of Channels, and Bits Per Sample OSCL_EXPORT_REF int32 pv_audio_config_parser(pvAudioConfigParserInputs *aInputs, pvAudioConfigParserOutputs *aOutputs) { bool bBitStreamValid = true; bool bBitStreamSupported = true; if (aInputs->iMimeType == PVMF_MIME_WMA) { uint16 wdata; uint32 dwdata; uint32 AvgBytesPerSec; uint16 AdvancedEncodeOpt; /**** decoder header *******/ uint8* tp = aInputs->inPtr; LoadWORD(wdata , tp); switch (wdata) { // WMA Lossless case WAVE_FORMAT_WMAUDIO_LOSSLESS: { if (aInputs->inBytes < 36) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); AvgBytesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); // Round up to the byte to get the container size aOutputs->BitsPerSample = 8 * ((wdata + 7) / 8); // Has V3 specific info tp = aInputs->inPtr + 34; LoadWORD(wdata , tp); AdvancedEncodeOpt = wdata; #if !defined(BUILD_WMALSL) bBitStreamSupported = false; #endif // BUILD_WMALSL // more limits according to the current PV WMA implementation // do not supoprt multi-channel if (aOutputs->Channels > 2) { bBitStreamSupported = false; break; } // do not support 24-bit if (aOutputs->BitsPerSample > 16) { bBitStreamSupported = false; break; } } break; // WMA Pro, Pro+ case WAVE_FORMAT_WMAUDIO3: { if (aInputs->inBytes < 36) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); AvgBytesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); //iValidBitsPerSample // Round up to the byte to get the container size aOutputs->BitsPerSample = 8 * ((wdata + 7) / 8); // Has V3 specific info tp = aInputs->inPtr + 34; LoadWORD(wdata , tp); AdvancedEncodeOpt = wdata; #if !defined(BUILD_WMAPRO) bBitStreamSupported = false; break; #endif // BUILD_WMAPRO #if !defined(BUILD_WMAPROPLUS) if (0 != (AdvancedEncodeOpt & ENCOPT4_PLUSVER)) { bBitStreamSupported = false; break; } #endif // BUILD_WMAPROPLUS // more limits according to the current PV WMA implementation // do not supoprt multi-channel if (aOutputs->Channels > 2) { bBitStreamSupported = false; break; } // do not support 24-bit if (aOutputs->BitsPerSample > 16) { bBitStreamSupported = false; break; } #if defined(WMAPLUS_64KBPS_PROFILE_ONLY) // limit to M0-profile bitrate and sampling rate if (AvgBytesPerSec > 192000 || aOutputs->SamplesPerSec > 48000) { bBitStreamSupported = false; break; } // only decode PLUSV1 (not including PLUSV1ALT) if (ENCOPT4_PLUSV1 != (AdvancedEncodeOpt & ENCOPT4_PLUSVER)) { bBitStreamSupported = false; break; } #endif // WMAPLUS_64KBPS_PROFILE_ONLY } break; //WMA Standard case WAVE_FORMAT_WMAUDIO2: { if (aInputs->inBytes < 28) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); aOutputs->BitsPerSample = wdata; if (aOutputs->SamplesPerSec > 48000) { // not a valid sample rate for WMA Std spec bBitStreamValid = false; break; } if (aOutputs->Channels > 2) { // not a valid number of channels for the WMA Std spec bBitStreamValid = false; break; } if (aOutputs->BitsPerSample != 16) { // not a valid number of bits per sample for the WMA Std spec bBitStreamValid = false; break; } #if !defined(BUILD_WMASTD) bBitStreamSupported = false; #endif // BUILD_WMASTD } break; //WMA Standard (bitstream v1) case WAVE_FORMAT_MSAUDIO1: { if (aInputs->inBytes < 22) { bBitStreamValid = false; break; } tp = aInputs->inPtr + 4; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; tp = aInputs->inPtr + 2; LoadWORD(wdata , tp); aOutputs->Channels = wdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); aOutputs->BitsPerSample = wdata; if (aOutputs->SamplesPerSec > 48000) { // not a valid sample rate for WMA Std spec bBitStreamValid = false; break; } if (aOutputs->Channels > 2) { // not a valid number of channels for the WMA Std spec bBitStreamValid = false; break; } if (aOutputs->BitsPerSample != 16) { // not a valid number of bits per sample for the WMA Std spec bBitStreamValid = false; break; } #if !defined(BUILD_WMASTD) bBitStreamSupported = false; #endif // BUILD_WMASTD } break; // WMA Voice case WAVE_FORMAT_MSSPEECH: { if (aInputs->inBytes < 18) { bBitStreamValid = false; break; } tp = aInputs->inPtr + 4; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; tp = aInputs->inPtr + 8; LoadDWORD(dwdata, tp); //AvgBytesPerSec = dwdata; tp = aInputs->inPtr + 12; LoadWORD(wdata , tp); //BlockAlign = wdata; tp = aInputs->inPtr + 2; LoadWORD(wdata , tp); aOutputs->Channels = wdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); aOutputs->BitsPerSample = wdata; #if !defined(BUILD_WMAVOICE) bBitStreamSupported = false; #endif // BUILD_WMAVOICE } break; case WAVE_FORMAT_WMASPDIF: case WAVE_FORMAT_WMAUDIO2_ES: case WAVE_FORMAT_WMAUDIO3_ES: case WAVE_FORMAT_WMAUDIO_LOSSLESS_ES: { // these formats aren't supported bBitStreamSupported = false; } break; default: { // invalid wma format bBitStreamValid = false; } } } else if (aInputs->iMimeType == PVMF_MIME_MPEG4_AUDIO || // AAC aInputs->iMimeType == PVMF_MIME_3640 || aInputs->iMimeType == PVMF_MIME_LATM || aInputs->iMimeType == PVMF_MIME_ADIF || aInputs->iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO || aInputs->iMimeType == PVMF_MIME_AAC_SIZEHDR) { int32 bytes_consumed, status; uint8 aAudioObjectType, SamplingRateIndex; uint32 NumChannels; bytes_consumed = (int32)aInputs->inBytes; status = GetActualAacConfig(aInputs->inPtr, &aAudioObjectType, &bytes_consumed, &SamplingRateIndex, &NumChannels); aOutputs->Channels = (uint16)NumChannels; if (aOutputs->Channels > 2) { // not a valid number of channels for the AAC bBitStreamValid = false; } } if (!bBitStreamValid) { bBitStreamSupported = false; } return (bBitStreamSupported ? 1 : 0); }
// This routine parses the wma config header and returns Sampling Rate, Number of Channels, and Bits Per Sample // The header info is checked for validation and support OSCL_EXPORT_REF int32 pv_audio_config_parser(pvAudioConfigParserInputs *aInputs, pvAudioConfigParserOutputs *aOutputs) { bool bBitStreamValid = true; bool bBitStreamSupported = true; #if defined(BUILD_OLDWMAAUDIOLIB) //AdvancedEncodeOpt #define ENCOPT4_PLUSVER 0xe000 #define ENCOPT4_PLUSV1 0xc000 #define ENCOPT4_PLUSV1ALT 0x8000 #define ENCOPT4_PLUSV2 0x2000 #define ENCOPT4_PLUSV3 0x4000 if (aInputs->iMimeType == PVMF_MIME_WMA) { uint16 wdata; uint32 dwdata; uint32 AvgBytesPerSec; uint16 AdvancedEncodeOpt; /**** decoder header *******/ uint8* tp = aInputs->inPtr; LoadWORD(wdata , tp); if (wdata == WAVE_FORMAT_PLAYREADY) { tp += aInputs->inBytes - 4; // skip ahead to check the last 2 bytes. LoadWORD(wdata, tp); tp = aInputs->inPtr + 2; //restart from this location. } switch (wdata) { // WMA Lossless case WAVE_FORMAT_WMAUDIO_LOSSLESS: { if (aInputs->inBytes < 36) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); AvgBytesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); // Round up to the byte to get the container size aOutputs->BitsPerSample = 8 * ((wdata + 7) / 8); // Has V3 specific info tp = aInputs->inPtr + 34; LoadWORD(wdata , tp); AdvancedEncodeOpt = wdata; bBitStreamSupported = false; // more limits according to the current PV WMA implementation // do not supoprt multi-channel if (aOutputs->Channels > 2) { bBitStreamSupported = false; break; } // do not support 24-bit if (aOutputs->BitsPerSample > 16) { bBitStreamSupported = false; break; } } break; // WMA Pro, Pro+ case WAVE_FORMAT_WMAUDIO3: { if (aInputs->inBytes < 36) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); AvgBytesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); //iValidBitsPerSample // Round up to the byte to get the container size aOutputs->BitsPerSample = 8 * ((wdata + 7) / 8); // Has V3 specific info tp = aInputs->inPtr + 34; LoadWORD(wdata , tp); AdvancedEncodeOpt = wdata; // more limits according to the current PV WMA implementation // do not supoprt multi-channel if (aOutputs->Channels > 2) { bBitStreamSupported = false; break; } // do not support 24-bit if (aOutputs->BitsPerSample > 16) { bBitStreamSupported = false; break; } // limit to M0-profile bitrate and sampling rate if (AvgBytesPerSec > 192000 || aOutputs->SamplesPerSec > 48000) { bBitStreamSupported = false; break; } // only decode PLUSV1 (not including PLUSV1ALT) if (ENCOPT4_PLUSV1 != (AdvancedEncodeOpt & ENCOPT4_PLUSVER)) { bBitStreamSupported = false; break; } } break; //WMA Standard case WAVE_FORMAT_WMAUDIO2: { if (aInputs->inBytes < 28) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); aOutputs->BitsPerSample = wdata; if (aOutputs->SamplesPerSec > 48000) { // not a valid sample rate for WMA Std spec bBitStreamValid = false; break; } if (aOutputs->Channels > 2) { // not a valid number of channels for the WMA Std spec bBitStreamValid = false; break; } if (aOutputs->BitsPerSample != 16) { // not a valid number of bits per sample for the WMA Std spec bBitStreamValid = false; break; } } break; //WMA Standard (bitstream v1) case WAVE_FORMAT_MSAUDIO1: { if (aInputs->inBytes < 22) { bBitStreamValid = false; break; } tp = aInputs->inPtr + 4; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; tp = aInputs->inPtr + 2; LoadWORD(wdata , tp); aOutputs->Channels = wdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); aOutputs->BitsPerSample = wdata; if (aOutputs->SamplesPerSec > 48000) { // not a valid sample rate for WMA Std spec bBitStreamValid = false; break; } if (aOutputs->Channels > 2) { // not a valid number of channels for the WMA Std spec bBitStreamValid = false; break; } if (aOutputs->BitsPerSample != 16) { // not a valid number of bits per sample for the WMA Std spec bBitStreamValid = false; break; } } break; // WMA Voice case WAVE_FORMAT_WMAVOICE9: { if (aInputs->inBytes < 64) // sizeof(WMAVOICEWAVEFORMAT) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); // wmavFormat.wfx.nAvgBytesPerSec LoadWORD(wdata, tp); // wmavFormat.wfx.nBlockAlign = wdata; LoadWORD(wdata, tp); aOutputs->BitsPerSample = wdata; // WMAVoice is always mono, 16-bit if (aOutputs->Channels != 1) { bBitStreamValid = false; } if (aOutputs->BitsPerSample != 16) { bBitStreamValid = false; } if ((aOutputs->SamplesPerSec != 8000) && (aOutputs->SamplesPerSec != 11025) && (aOutputs->SamplesPerSec != 16000) && (aOutputs->SamplesPerSec != 22050)) { bBitStreamValid = false; } } break; case WAVE_FORMAT_WMASPDIF: case WAVE_FORMAT_WMAUDIO2_ES: case WAVE_FORMAT_WMAUDIO3_ES: case WAVE_FORMAT_WMAUDIO_LOSSLESS_ES: { // these formats aren't supported bBitStreamSupported = false; } break; default: { // invalid wma format bBitStreamValid = false; } } } #else // BUILD_OLDWMAAUDIOLIB if (aInputs->iMimeType == PVMF_MIME_WMA) { uint16 wdata; uint32 dwdata; uint32 AvgBytesPerSec; uint16 AdvancedEncodeOpt; /**** decoder header *******/ uint8* tp = aInputs->inPtr; LoadWORD(wdata , tp); if (wdata == WAVE_FORMAT_PLAYREADY) { tp += aInputs->inBytes - 4; // skip ahead to check the last 2 bytes. LoadWORD(wdata, tp); tp = aInputs->inPtr + 2; //restart from this location. } switch (wdata) { // WMA Lossless case WAVE_FORMAT_WMAUDIO_LOSSLESS: { if (aInputs->inBytes < 36) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); AvgBytesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); // Round up to the byte to get the container size aOutputs->BitsPerSample = 8 * ((wdata + 7) / 8); // Has V3 specific info tp = aInputs->inPtr + 34; LoadWORD(wdata , tp); AdvancedEncodeOpt = wdata; #if !defined(WMA_AUDIO_SUPPORTED) bBitStreamSupported = false; break; #endif // WMA_AUDIO_SUPPORTED if (aOutputs->Channels > 8) { bBitStreamSupported = false; break; } #if !defined(PV_WMA_ENABLE_MULTICH) // device does not support multichannel, therefore automatically downmix if (aOutputs->Channels > 2) { aOutputs->Channels = 2; } #endif // PV_WMA_ENABLE_MULTICH #if !defined(PV_WMA_ENABLE_24BIT) // do not support 24-bit, therefore automaticall requantize if (aOutputs->BitsPerSample > 16) { aOutputs->BitsPerSample = 16; } #endif // PV_WMA_ENABLE_24BIT #if !defined(PV_WMA_ENABLE_HIGHFS) // hardware does not support sampling rates greater than 48kHz, //lossless does not have half-transform downsampling if (aOutputs->SamplesPerSec > 48000) { bBitStreamSupported = false; break; } #endif // PV_WMA_ENABLE_HIGHFS } break; // WMA Pro, LBRv1, LBRv2, LBRv3 case WAVE_FORMAT_WMAUDIO3: { if (aInputs->inBytes < 36) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); AvgBytesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); //iValidBitsPerSample // Round up to the byte to get the container size aOutputs->BitsPerSample = 8 * ((wdata + 7) / 8); // Has V3 specific info tp = aInputs->inPtr + 34; LoadWORD(wdata , tp); AdvancedEncodeOpt = wdata; #if !defined(WMA_AUDIO_SUPPORTED) bBitStreamSupported = false; break; #endif // this is the max of the format. the codec will downmix to stereo if (aOutputs->Channels > 8) { bBitStreamSupported = false; break; } #if !defined(PV_WMA_ENABLE_MULTICH) // device does not support multichannel, therefore automatically downmix if (aOutputs->Channels > 2) { aOutputs->Channels = 2; } #endif // PV_WMA_ENABLE_MULTICH #if !defined(PV_WMA_ENABLE_24BIT) // do not support 24-bit, therefore automatically requantize if (aOutputs->BitsPerSample == 24) { aOutputs->BitsPerSample = 16; } #endif // PV_WMA_ENABLE_24BIT #if !defined(PV_WMA_ENABLE_HIGHFS) // hardware does not support sampling rates greater than 48kHz, // however, WMA Pro has half-transform downsampling if (aOutputs->SamplesPerSec > 48000) { aOutputs->SamplesPerSec = aOutputs->SamplesPerSec / 2; } #endif // PV_WMA_ENABLE_HIGHFS } break; //WMA Standard case WAVE_FORMAT_WMAUDIO2: { if (aInputs->inBytes < 28) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); aOutputs->BitsPerSample = wdata; if (aOutputs->SamplesPerSec > 48000) { // not a valid sample rate for WMA Std spec bBitStreamValid = false; break; } if (aOutputs->Channels > 2) { // not a valid number of channels for the WMA Std spec bBitStreamValid = false; break; } if (aOutputs->BitsPerSample != 16) { // not a valid number of bits per sample for the WMA Std spec bBitStreamValid = false; break; } #if !defined(WMA_AUDIO_SUPPORTED) bBitStreamSupported = false; #endif // WMA_AUDIO_SUPPORTED } break; //WMA Standard (bitstream v1) case WAVE_FORMAT_MSAUDIO1: { if (aInputs->inBytes < 22) { bBitStreamValid = false; break; } tp = aInputs->inPtr + 4; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; tp = aInputs->inPtr + 2; LoadWORD(wdata , tp); aOutputs->Channels = wdata; tp = aInputs->inPtr + 14; LoadWORD(wdata , tp); aOutputs->BitsPerSample = wdata; if (aOutputs->SamplesPerSec > 48000) { // not a valid sample rate for WMA Std spec bBitStreamValid = false; break; } if (aOutputs->Channels > 2) { // not a valid number of channels for the WMA Std spec bBitStreamValid = false; break; } if (aOutputs->BitsPerSample != 16) { // not a valid number of bits per sample for the WMA Std spec bBitStreamValid = false; break; } #if !defined(WMA_AUDIO_SUPPORTED) bBitStreamSupported = false; #endif // WMA_AUDIO_SUPPORTED } break; // WMA Voice case WAVE_FORMAT_WMAVOICE9: { if (aInputs->inBytes < 64) // sizeof(WMAVOICEWAVEFORMAT) { bBitStreamValid = false; break; } LoadWORD(wdata, tp); aOutputs->Channels = wdata; LoadDWORD(dwdata, tp); aOutputs->SamplesPerSec = dwdata; LoadDWORD(dwdata, tp); // wmavFormat.wfx.nAvgBytesPerSec LoadWORD(wdata, tp); // wmavFormat.wfx.nBlockAlign = wdata; LoadWORD(wdata, tp); aOutputs->BitsPerSample = wdata; // WMAVoice is always mono, 16-bit if (aOutputs->Channels != 1) { bBitStreamValid = false; } if (aOutputs->BitsPerSample != 16) { bBitStreamValid = false; } if ((aOutputs->SamplesPerSec != 8000) && (aOutputs->SamplesPerSec != 11025) && (aOutputs->SamplesPerSec != 16000) && (aOutputs->SamplesPerSec != 22050)) { bBitStreamValid = false; } #if !defined(WMA_VOICE_SUPPORTED) bBitStreamSupported = false; #endif // WMA_VOICE_SUPPORTED } break; case WAVE_FORMAT_WMASPDIF: case WAVE_FORMAT_WMAUDIO2_ES: case WAVE_FORMAT_WMAUDIO3_ES: case WAVE_FORMAT_WMAUDIO_LOSSLESS_ES: { // these formats aren't supported bBitStreamSupported = false; } break; default: { // invalid wma format bBitStreamValid = false; } } } #endif // BUILD_OLDWMAAUDIOLIB else if (aInputs->iMimeType == PVMF_MIME_MPEG4_AUDIO || // AAC aInputs->iMimeType == PVMF_MIME_3640 || aInputs->iMimeType == PVMF_MIME_LATM || aInputs->iMimeType == PVMF_MIME_ADIF || aInputs->iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO || aInputs->iMimeType == PVMF_MIME_AAC_SIZEHDR) { int32 bytes_consumed, status; uint8 aAudioObjectType, SamplingRateIndex; uint32 NumChannels; uint32 SamplesPerFrame; const uint32 SampleFreqTable[13] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350 }; bytes_consumed = (int32)aInputs->inBytes; status = GetActualAacConfig(aInputs->inPtr, &aAudioObjectType, &bytes_consumed, &SamplingRateIndex, &NumChannels, &SamplesPerFrame); if (status != 0)//error { bBitStreamValid = false; } aOutputs->Channels = (uint16)NumChannels; if (aOutputs->Channels > 2) { // not a valid number of channels for the AAC bBitStreamValid = false; } if (SamplingRateIndex < 13) { aOutputs->SamplesPerSec = SampleFreqTable[(uint32)SamplingRateIndex]; } else { // not a valid sampling rate for the AAC bBitStreamValid = false; } aOutputs->SamplesPerFrame = SamplesPerFrame; } else if (aInputs->iMimeType == PVMF_MIME_REAL_AUDIO) //Real Audio { // use these as default value, let decoder discover the actual size and perform port reconfig aOutputs->Channels = RA_DEFAULT_NUM_CHANNELS; aOutputs->SamplesPerSec = RA_DEFAULT_SAMPLE_RATE; aOutputs->SamplesPerFrame = RA_DEFAULT_SAMPLES_PER_FRAME; } if (!bBitStreamValid) { bBitStreamSupported = false; } return (bBitStreamSupported ? 1 : 0); }
WMAERR WMA_LoadMarkerObject(tWMAFileHdrStateInternal *pInt, DWORD cbSize, int iIndex) { BYTE *pData; DWORD cbWanted; DWORD cbActual; DWORD cbObjectOffset = 0; GUID m_gMarkerStrategy; WORD m_wAlignment; WORD m_wNameLen; WORD tw; unsigned int i, j; if(pInt == NULL) { return WMAERR_INVALIDARG; } cbSize -= MIN_OBJECT_SIZE; cbWanted = 24; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadGUID (m_gMarkerStrategy, pData); LoadDWORD(pInt->m_dwMarkerNum, pData); LoadWORD (m_wAlignment, pData); LoadWORD (m_wNameLen, pData); //pInt->m_pMarkers = (MarkerEntry *) malloc(sizeof(MarkerEntry)*pInt->m_dwMarkerNum); //NQF+ if( pInt->m_dwMarkerNum == 0) { pInt->currPacketOffset += cbSize; return WMAERR_OK; } else if ( iIndex < 0 ) { //for query number of Markers pInt->currPacketOffset += cbSize; return WMAERR_OK; } else if ( iIndex >= (int) pInt -> m_dwMarkerNum) { pInt->currPacketOffset += cbSize; return WMAERR_BUFFERTOOSMALL; //NQF_temp } for (j = 0; j <= (unsigned int) iIndex; j++) { cbWanted = 18; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadQWORD(pInt->m_pMarker->m_qOffset, pData); LoadQWORD(pInt->m_pMarker->m_qtime, pData); LoadWORD (pInt->m_pMarker->m_wEntryLen, pData); cbWanted = pInt->m_pMarker->m_wEntryLen; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadDWORD(pInt->m_pMarker->m_dwSendTime, pData); LoadDWORD(pInt->m_pMarker->m_dwFlags, pData); LoadDWORD(pInt->m_pMarker->m_dwDescLen, pData); //pInt->m_pMarkers[j].m_pwDescName = (WORD *)malloc(sizeof(WORD)*pInt->m_pMarkers[j].m_dwDescLen); for (i=0;i<pInt->m_pMarker->m_dwDescLen && i < DESC_NAME_MAX_LENGTH; i++) { LoadWORD(tw, pData); pInt->m_pMarker->m_pwDescName[i] = tw; } } pInt->currPacketOffset += cbSize; return WMAERR_OK; }
WMAERR WMA_LoadLicenseStoreObject(tWMAFileHdrStateInternal *pInt, DWORD cbSize) { BYTE *pData; DWORD cbWanted; DWORD cbDone; DWORD cbActual; DWORD m_dwFlag; DWORD cbObjectOffset = 0; if(pInt == NULL) { return WMAERR_INVALIDARG; } cbSize -= MIN_OBJECT_SIZE; cbWanted = 8; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadDWORD(m_dwFlag, pData); LoadDWORD(pInt->m_dwLicenseLen, pData); cbWanted = pInt->m_dwLicenseLen; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_NOTDONE; } // pInt->m_pLicData = malloc(cbWanted); cbDone = 0; while (cbWanted) { cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); // memcpy(pInt->m_pLicData + cbDone, pData, cbActual); cbObjectOffset += cbActual; cbWanted -= cbActual; cbDone += cbActual; if(cbActual == 0) { return WMAERR_FAIL; } } // pInt->cbCDOffset = pInt->currPacketOffset + cbObjectOffset; pInt->currPacketOffset += cbSize; return WMAERR_OK; }
WMAERR WMA_LoadEncryptionObject(tWMAFileHdrStateInternal *pInt, DWORD cbSize) { DWORD cbBlock; BYTE *pData; DWORD cbWanted; DWORD cbActual; DWORD cbObjectOffset = 0; BYTE *sData,*cDaTa; int i=0; if(pInt == NULL) { return WMAERR_INVALIDARG; } cbSize -= MIN_OBJECT_SIZE; pInt->cbSecretData = 0; cbWanted = sizeof(DWORD); if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadDWORD(pInt->cbSecretData, pData); if(pInt->cbSecretData) { cbWanted = pInt->cbSecretData; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; // memcpy(pInt->pbSecretData, pData, (int)cbActual); cDaTa=pInt->pbSecretData; sData =pData; for(i=0;i<(int)cbActual;++i) *cDaTa++ =*sData++; // iBytesRead = num_bytes; } cbWanted = sizeof(DWORD); if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadDWORD(cbBlock, pData); if(cbBlock) { cbWanted = cbBlock; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; // memcpy(pInt->pbType, pData, (int)cbActual); cDaTa=pInt->pbType; sData =pData; for(i=0;i<(int)cbActual;++i) *cDaTa++ =*sData++; } cbWanted = sizeof(DWORD); if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadDWORD(cbBlock, pData); if(cbBlock) { cbWanted = cbBlock; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; // memcpy(pInt->pbKeyID, pData, (int)cbActual); cDaTa=pInt->pbKeyID; sData =pData; for(i=0;i<(int)cbActual;++i) *cDaTa++ =*sData++; } cbWanted = sizeof(DWORD); if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadDWORD(cbBlock, pData); if(cbBlock) { cbWanted = cbBlock; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } while (cbWanted>0) { cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); cbObjectOffset += cbActual; cbWanted -= cbActual; } } pInt->currPacketOffset += cbSize; return WMAERR_OK; }
WMAERR WMA_LoadAudioObject(tWMAFileHdrStateInternal *pInt, DWORD cbSize, int isFull) { GUID streamType; GUID ecStrategy; QWORD qwOffset; DWORD cbTypeSpecific; DWORD cbErrConcealment; WORD wStreamNum; DWORD dwJunk; DWORD nBlocksPerObject; AsfXAcmAudioErrorMaskingData *pScramblingData; // WAVEFORMATEX *pFmt; BYTE *pData; DWORD cbWanted; DWORD cbActual; WORD tw; DWORD tdw; const BYTE *tp; DWORD cbObjectOffset = 0; if(pInt == NULL) { return WMAERR_INVALIDARG; } cbSize -= MIN_OBJECT_SIZE; cbWanted = 2*sizeof(GUID) + sizeof(QWORD) + 3*sizeof(DWORD) + sizeof(WORD); if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; LoadGUID(streamType, pData); LoadGUID(ecStrategy, pData); LoadQWORD(qwOffset, pData); LoadDWORD(cbTypeSpecific, pData); LoadDWORD(cbErrConcealment, pData); LoadWORD(wStreamNum, pData); LoadDWORD(dwJunk, pData); wStreamNum &= 0x7F; if( !WMA_IsEqualGUID( &CLSID_AsfXStreamTypeAcmAudio, &streamType ) ) { /* Skip over the rest */ pInt->currPacketOffset += cbSize; return WMAERR_OK; } /* Type specific */ pInt->wAudioStreamId = wStreamNum; //Amit if(cbTypeSpecific > 0) { cbWanted = cbTypeSpecific; if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbActual; tp = pData; LoadWORD (tw ,tp); switch(tw) { case WAVE_FORMAT_WMAUDIO2: if(cbTypeSpecific < 28 /*sizeof(WMAUDIO2WAVEFORMAT)*/) { return WMAERR_FAIL; } pInt->nVersion = 2; tp = pData + 4; LoadDWORD(tdw,tp); pInt->nSamplesPerSec = tdw; tp = pData + 8; LoadDWORD(tdw,tp); pInt->nAvgBytesPerSec = tdw; tp = pData + 12; LoadWORD (tw ,tp); pInt->nBlockAlign = tw; tp = pData + 2; LoadWORD (tw ,tp); pInt->nChannels = tw; tp = pData + 22; LoadWORD (tw ,tp); tp = pData + 18; LoadDWORD(tdw,tp); pInt->nSamplesPerBlock = tdw; pInt->nEncodeOpt = tw; break; case WAVE_FORMAT_MSAUDIO1: if(cbTypeSpecific < 22 /*sizeof(MSAUDIO1WAVEFORMAT)*/) { return WMAERR_FAIL; } pInt->nVersion = 1; tp = pData + 4; LoadDWORD(tdw,tp); pInt->nSamplesPerSec = tdw; tp = pData + 8; LoadDWORD(tdw,tp); pInt->nAvgBytesPerSec = tdw; tp = pData + 12; LoadWORD (tw ,tp); pInt->nBlockAlign = tw; tp = pData + 2; LoadWORD (tw ,tp); pInt->nChannels = tw; tp = pData + 20; LoadWORD (tw,tp); pInt->nEncodeOpt = tw; tp = pData + 18; LoadWORD (tw,tp); pInt->nSamplesPerBlock = tw; break; default: // unknown... return WMAERR_FAIL; } } /* Error concealment - this can get as big as 400!!! */ if(cbErrConcealment > 0) { if(WMA_IsEqualGUID(&CLSID_AsfXSignatureAudioErrorMaskingStrategy, &ecStrategy)) { cbWanted = 9;//sizeof(AsfXSignatureAudioErrorMaskingData); } else if(WMA_IsEqualGUID(&CLSID_AsfXAcmAudioErrorMaskingStrategy, &ecStrategy)) { // cbWanted = sizeof(AsfXAcmAudioErrorMaskingData); cbWanted = 8; } else { return WMAERR_FAIL; } if(cbObjectOffset + cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset + cbObjectOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } cbObjectOffset += cbErrConcealment; // Skip over the rest - cbActual; if(WMA_IsEqualGUID(&CLSID_AsfXSignatureAudioErrorMaskingStrategy, &ecStrategy)) { pInt->cbAudioSize = ((AsfXSignatureAudioErrorMaskingData *)pData)->maxObjectSize; } else if(WMA_IsEqualGUID(&CLSID_AsfXAcmAudioErrorMaskingStrategy, &ecStrategy)) { pScramblingData = (AsfXAcmAudioErrorMaskingData *)pData; pInt->cbAudioSize = (DWORD)(pScramblingData->virtualPacketLen*pScramblingData->span); // pInt->cbAudioSize = (DWORD)((*(WORD*)(pData+1)) * ((WORD)(*pData))); if (pScramblingData->span >1) return WMAERR_FAIL; } else { return WMAERR_FAIL; } } nBlocksPerObject = pInt->cbAudioSize/pInt->nBlockAlign; pInt->cbAudioSize = nBlocksPerObject*pInt->nSamplesPerBlock*pInt->nChannels*2; /* use all */ pInt->currPacketOffset += cbSize; return WMAERR_OK; }
WMAERR WMA_LoadPropertiesObject(tWMAFileHdrStateInternal *pInt, DWORD cbSize, int isFull) { GUID mmsId; QWORD qwTotalSize; QWORD qwCreateTime; QWORD qwPackets; QWORD qwPlayDuration; QWORD qwSendDuration; QWORD qwPreroll; DWORD dwFlags; DWORD dwMinPacketSize; DWORD dwMaxPacketSize; DWORD dwMaxBitrate; BYTE *pData; DWORD cbWanted; DWORD cbActual; if(pInt == NULL) { return WMAERR_INVALIDARG; } cbSize -= MIN_OBJECT_SIZE; cbWanted = sizeof(GUID) + 6*sizeof(QWORD) + 4*sizeof(DWORD); if(cbWanted > cbSize) { return WMAERR_BUFFERTOOSMALL; } cbActual = WMAFileCBGetData((tHWMAFileState *)pInt, pInt->currPacketOffset, cbWanted, &pData); if(cbActual != cbWanted) { return WMAERR_BUFFERTOOSMALL; } LoadGUID(mmsId, pData); LoadQWORD(qwTotalSize, pData); LoadQWORD(qwCreateTime, pData); LoadQWORD(qwPackets, pData); LoadQWORD(qwPlayDuration, pData); LoadQWORD(qwSendDuration, pData); LoadQWORD(qwPreroll, pData); LoadDWORD(dwFlags, pData); LoadDWORD(dwMinPacketSize, pData); LoadDWORD(dwMaxPacketSize, pData); LoadDWORD(dwMaxBitrate, pData); if(dwMinPacketSize != dwMaxPacketSize || (qwPackets.dwLo == 0 && qwPackets.dwHi == 0)) { return WMAERR_FAIL; } pInt->cbPacketSize = dwMaxPacketSize; pInt->cPackets = qwPackets.dwLo; pInt->msDuration = HnsQWORDtoMsDWORD(qwPlayDuration); pInt->msPreroll = qwPreroll.dwLo; pInt->currPacketOffset += cbSize; return WMAERR_OK; }