00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ADTSAudioFileSource.hh"
00022 #include "InputFile.hh"
00023 #include <GroupsockHelper.hh>
00024
00026
00027 static unsigned const samplingFrequencyTable[16] = {
00028 96000, 88200, 64000, 48000,
00029 44100, 32000, 24000, 22050,
00030 16000, 12000, 11025, 8000,
00031 7350, 0, 0, 0
00032 };
00033
00034 ADTSAudioFileSource*
00035 ADTSAudioFileSource::createNew(UsageEnvironment& env, char const* fileName) {
00036 FILE* fid = NULL;
00037 do {
00038 fid = OpenInputFile(env, fileName);
00039 if (fid == NULL) break;
00040
00041
00042
00043 unsigned char fixedHeader[4];
00044 if (fread(fixedHeader, 1, sizeof fixedHeader, fid) < sizeof fixedHeader) break;
00045
00046
00047 if (!(fixedHeader[0] == 0xFF && (fixedHeader[1]&0xF0) == 0xF0)) {
00048 env.setResultMsg("Bad 'syncword' at start of ADTS file");
00049 break;
00050 }
00051
00052
00053 u_int8_t profile = (fixedHeader[2]&0xC0)>>6;
00054 if (profile == 3) {
00055 env.setResultMsg("Bad (reserved) 'profile': 3 in first frame of ADTS file");
00056 break;
00057 }
00058
00059
00060 u_int8_t sampling_frequency_index = (fixedHeader[2]&0x3C)>>2;
00061 if (samplingFrequencyTable[sampling_frequency_index] == 0) {
00062 env.setResultMsg("Bad 'sampling_frequency_index' in first frame of ADTS file");
00063 break;
00064 }
00065
00066
00067 u_int8_t channel_configuration
00068 = ((fixedHeader[2]&0x01)<<2)|((fixedHeader[3]&0xC0)>>6);
00069
00070
00071
00072 #ifndef _WIN32_WCE
00073 rewind(fid);
00074 #else
00075 fseek(fid, SEEK_SET,0);
00076 #endif
00077 #ifdef DEBUG
00078 fprintf(stderr, "Read first frame: profile %d, "
00079 "sampling_frequency_index %d => samplingFrequency %d, "
00080 "channel_configuration %d\n",
00081 profile,
00082 sampling_frequency_index, samplingFrequencyTable[sampling_frequency_index],
00083 channel_configuration);
00084 #endif
00085 return new ADTSAudioFileSource(env, fid, profile,
00086 sampling_frequency_index, channel_configuration);
00087 } while (0);
00088
00089
00090 CloseInputFile(fid);
00091 return NULL;
00092 }
00093
00094 ADTSAudioFileSource
00095 ::ADTSAudioFileSource(UsageEnvironment& env, FILE* fid, u_int8_t profile,
00096 u_int8_t samplingFrequencyIndex, u_int8_t channelConfiguration)
00097 : FramedFileSource(env, fid) {
00098 fSamplingFrequency = samplingFrequencyTable[samplingFrequencyIndex];
00099 fNumChannels = channelConfiguration == 0 ? 2 : channelConfiguration;
00100 fuSecsPerFrame
00101 = (1024*1000000) / fSamplingFrequency;
00102
00103
00104 unsigned char audioSpecificConfig[2];
00105 u_int8_t const audioObjectType = profile + 1;
00106 audioSpecificConfig[0] = (audioObjectType<<3) | (samplingFrequencyIndex>>1);
00107 audioSpecificConfig[1] = (samplingFrequencyIndex<<7) | (channelConfiguration<<3);
00108 sprintf(fConfigStr, "%02X%02x", audioSpecificConfig[0], audioSpecificConfig[1]);
00109 }
00110
00111 ADTSAudioFileSource::~ADTSAudioFileSource() {
00112 CloseInputFile(fFid);
00113 }
00114
00115
00116
00117 void ADTSAudioFileSource::doGetNextFrame() {
00118
00119 unsigned char headers[7];
00120 if (fread(headers, 1, sizeof headers, fFid) < sizeof headers
00121 || feof(fFid) || ferror(fFid)) {
00122
00123 handleClosure(this);
00124 return;
00125 }
00126
00127
00128 Boolean protection_absent = headers[1]&0x01;
00129 u_int16_t frame_length
00130 = ((headers[3]&0x03)<<11) | (headers[4]<<3) | ((headers[5]&0xE0)>>5);
00131 #ifdef DEBUG
00132 u_int16_t syncword = (headers[0]<<4) | (headers[1]>>4);
00133 fprintf(stderr, "Read frame: syncword 0x%x, protection_absent %d, frame_length %d\n", syncword, protection_absent, frame_length);
00134 if (syncword != 0xFFF) fprintf(stderr, "WARNING: Bad syncword!\n");
00135 #endif
00136 unsigned numBytesToRead
00137 = frame_length > sizeof headers ? frame_length - sizeof headers : 0;
00138
00139
00140 if (!protection_absent) {
00141 fseek(fFid, 2, SEEK_CUR);
00142 numBytesToRead = numBytesToRead > 2 ? numBytesToRead - 2 : 0;
00143 }
00144
00145
00146 if (numBytesToRead > fMaxSize) {
00147 fNumTruncatedBytes = numBytesToRead - fMaxSize;
00148 numBytesToRead = fMaxSize;
00149 }
00150 int numBytesRead = fread(fTo, 1, numBytesToRead, fFid);
00151 if (numBytesRead < 0) numBytesRead = 0;
00152 fFrameSize = numBytesRead;
00153 fNumTruncatedBytes += numBytesToRead - numBytesRead;
00154
00155
00156 if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
00157
00158 gettimeofday(&fPresentationTime, NULL);
00159 } else {
00160
00161 unsigned uSeconds = fPresentationTime.tv_usec + fuSecsPerFrame;
00162 fPresentationTime.tv_sec += uSeconds/1000000;
00163 fPresentationTime.tv_usec = uSeconds%1000000;
00164 }
00165
00166 fDurationInMicroseconds = fuSecsPerFrame;
00167
00168
00169 nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
00170 (TaskFunc*)FramedSource::afterGetting, this);
00171 }