Changeset 408
- Timestamp:
- 04/12/07 01:59:38 (2 years ago)
- Files:
-
- trunk/FFissionCodec/FFissionDecoder.cpp (modified) (7 diffs)
- trunk/FFissionCodec/FFissionDecoder.h (modified) (4 diffs)
- trunk/FFissionCodec/ringbuffer.cpp (added)
- trunk/FFissionCodec/ringbuffer.h (added)
- trunk/Perian.xcodeproj/project.pbxproj (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/FFissionCodec/FFissionDecoder.cpp
r407 r408 48 48 49 49 50 FFissionDecoder::FFissionDecoder(UInt32 inInputBufferByteSize) : FFissionCodec( inInputBufferByteSize)50 FFissionDecoder::FFissionDecoder(UInt32 inInputBufferByteSize) : FFissionCodec(0) 51 51 { 52 52 kIntPCMOutFormatFlag = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; … … 62 62 CAStreamBasicDescription theOutputFormat(kAudioStreamAnyRate, kAudioFormatLinearPCM, 0, 1, 0, 0, 16, kIntPCMOutFormatFlag); 63 63 AddOutputFormat(theOutputFormat); 64 65 inputBuffer.Initialize(inInputBufferByteSize); 66 outBufUsed = 0; 67 outBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; 68 outputBuffer = new Byte[outBufSize]; 64 69 } 65 70 … … 68 73 if (magicCookie) 69 74 delete[] magicCookie; 75 76 delete[] outputBuffer; 70 77 } 71 78 … … 76 83 77 84 FFissionCodec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize); 85 } 86 87 void FFissionDecoder::Uninitialize() 88 { 89 outBufUsed = 0; 90 inputBuffer.Zap(inputBuffer.GetDataAvailable()); 91 92 FFissionCodec::Uninitialize(); 93 } 94 95 void FFissionDecoder::Reset() 96 { 97 outBufUsed = 0; 98 inputBuffer.Zap(inputBuffer.GetDataAvailable()); 99 100 FFissionCodec::Reset(); 78 101 } 79 102 … … 122 145 CODEC_THROW(kAudioCodecBadPropertySizeError); 123 146 break; 124 } 147 148 case kAudioCodecPropertyInputBufferSize: 149 case kAudioCodecPropertyUsedInputBufferSize: 150 if (ioPropertyDataSize != sizeof(UInt32)) 151 CODEC_THROW(kAudioCodecBadPropertySizeError); 152 break; 153 } 154 125 155 switch (inPropertyID) { 126 156 case kAudioCodecPropertyNameCFString: … … 128 158 *(CFStringRef*)outPropertyData = name; 129 159 break; 160 161 case kAudioCodecPropertyInputBufferSize: 162 *reinterpret_cast<UInt32*>(outPropertyData) = inputBuffer.GetBufferByteSize(); 163 break; 164 165 case kAudioCodecPropertyUsedInputBufferSize: 166 *reinterpret_cast<UInt32*>(outPropertyData) = inputBuffer.GetDataAvailable(); 167 break; 130 168 131 169 default: … … 203 241 } 204 242 243 void FFissionDecoder::AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, 244 UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription) 245 { 246 const Byte *inData = (const Byte *)inInputData; 247 248 if (inPacketDescription && ioNumberPackets) { 249 for (int i = 0; i < ioNumberPackets; i++) { 250 UInt32 packetSize = inPacketDescription[i].mDataByteSize; 251 inputBuffer.In(inData + inPacketDescription[i].mStartOffset, packetSize); 252 } 253 } else { 254 // no packet description, assume cbr 255 UInt32 amountToCopy = FFMIN(mInputFormat.mBytesPerPacket * ioNumberPackets, ioInputDataByteSize); 256 UInt32 numPackets = amountToCopy / mInputFormat.mBytesPerPacket; 257 258 ioInputDataByteSize = amountToCopy; 259 ioNumberPackets = numPackets; 260 261 for (int i = 0; i < numPackets; i++) { 262 UInt32 packetSize = mInputFormat.mBytesPerPacket; 263 inputBuffer.In(inData, packetSize); 264 inData += mInputFormat.mBytesPerPacket; 265 } 266 } 267 } 268 205 269 UInt32 FFissionDecoder::ProduceOutputPackets(void* outOutputData, 206 UInt32& ioOutputDataByteSize, // number of bytes written to outOutputData 207 UInt32& ioNumberPackets, 208 AudioStreamPacketDescription* outPacketDescription) 209 { 210 // setup the return value, by assuming that everything is going to work 211 UInt32 theAnswer = kAudioCodecProduceOutputPacketSuccess; 270 UInt32& ioOutputDataByteSize, // number of bytes written to outOutputData 271 UInt32& ioNumberPackets, 272 AudioStreamPacketDescription* outPacketDescription) 273 { 274 UInt32 ans = kAudioCodecProduceOutputPacketSuccess; 212 275 213 276 if (!mIsInitialized) 214 277 CODEC_THROW(kAudioCodecStateError); 215 278 216 // clamp the number of packets to produce based on what is available in the input buffer 217 UInt32 inputPacketSize = avContext->channels * avContext->block_align; 218 UInt32 numberOfInputPackets = GetUsedInputBufferByteSize() / inputPacketSize; 219 220 if (ioNumberPackets < numberOfInputPackets) 221 { 222 numberOfInputPackets = ioNumberPackets; 223 } 224 else if (ioNumberPackets > numberOfInputPackets) 225 { 226 ioNumberPackets = numberOfInputPackets; 227 228 // this also means we need more input to satisfy the request so set the return value 229 theAnswer = kAudioCodecProduceOutputPacketNeedsMoreInputData; 230 } 231 232 UInt32 inputByteSize = numberOfInputPackets * inputPacketSize; 233 234 if(ioNumberPackets > 0) 235 { 236 // make sure that there is enough space in the output buffer for the encoded data 237 // it is an error to ask for more output than you pass in buffer space for 238 UInt32 theOutputByteSize = ioNumberPackets * avContext->frame_size * mOutputFormat.mBytesPerFrame; 239 ThrowIf(ioOutputDataByteSize < theOutputByteSize, static_cast<ComponentResult>(kAudioCodecNotEnoughBufferSpaceError), "ACAppleIMA4Decoder::ProduceOutputPackets: not enough space in the output buffer"); 240 241 // set the return value 242 ioOutputDataByteSize = theOutputByteSize; 243 244 // decode the input data for each channel 245 Byte* theInputData = GetBytes(inputByteSize); 246 247 int out_size = 0; 248 SInt16* theOutputData = reinterpret_cast<SInt16*>(outOutputData); 249 250 int len = avcodec_decode_audio(avContext, theOutputData, &out_size, theInputData, inputByteSize); 251 ioOutputDataByteSize = out_size; 252 253 ConsumeInputData(len); 254 } 255 else 256 { 257 // set the return value since we're not actually doing any work 258 ioOutputDataByteSize = 0; 259 } 260 261 if((theAnswer == kAudioCodecProduceOutputPacketSuccess) && (GetUsedInputBufferByteSize() >= inputPacketSize)) 262 { 263 // we satisfied the request, and there's at least one more full packet of data we can decode 264 // so set the return value 265 theAnswer = kAudioCodecProduceOutputPacketSuccessHasMore; 266 } 267 268 return theAnswer; 279 UInt32 written = 0; 280 ioNumberPackets = 0; 281 Byte *outData = (Byte *) outOutputData; 282 283 // we have leftovers from the last packet, use that first 284 if (outBufUsed > 0) { 285 int amountToCopy = FFMIN(outBufUsed, ioOutputDataByteSize); 286 memcpy(outData, outputBuffer, amountToCopy); 287 outBufUsed -= amountToCopy; 288 written += amountToCopy; 289 290 if (outBufUsed > 0) 291 memmove(outputBuffer, outputBuffer + amountToCopy, outBufUsed); 292 } 293 294 // loop until we satisfy the request or run out of input data 295 while (written < ioOutputDataByteSize && inputBuffer.GetNumPackets() > 0) { 296 int packetSize = inputBuffer.GetCurrentPacketSize(); 297 uint8_t *packet = inputBuffer.GetData(); 298 299 // decode one packet to our buffer 300 outBufUsed = outBufSize; 301 int len = avcodec_decode_audio2(avContext, (int16_t *)outputBuffer, &outBufUsed, packet, packetSize); 302 inputBuffer.Zap(len); 303 304 if (len < 0) { 305 Codecprintf(NULL, "Error decoding audio frame\n"); 306 inputBuffer.Zap(packetSize); 307 outBufUsed = 0; 308 ioOutputDataByteSize = written; 309 return kAudioCodecProduceOutputPacketFailure; 310 } 311 312 // copy up to the amount requested 313 int amountToCopy = FFMIN(outBufUsed, ioOutputDataByteSize - written); 314 memcpy(outData + written, outputBuffer, amountToCopy); 315 outBufUsed -= amountToCopy; 316 written += amountToCopy; 317 ioNumberPackets++; 318 319 // and save what's left over 320 if (outBufUsed > 0) 321 memmove(outputBuffer, outputBuffer + amountToCopy, outBufUsed); 322 } 323 324 if (written < ioOutputDataByteSize) 325 ans = kAudioCodecProduceOutputPacketNeedsMoreInputData; 326 else if (outBufUsed > written || inputBuffer.GetNumPackets() > 0) 327 // we have more left than what we wrote, or an entire other packet 328 ans = kAudioCodecProduceOutputPacketSuccessHasMore; 329 330 ioOutputDataByteSize = written; 331 332 return ans; 269 333 } 270 334 trunk/FFissionCodec/FFissionDecoder.h
r219 r408 25 25 #include "FFissionCodec.h" 26 26 #include "avcodec.h" 27 #include "RingBuffer.h" 27 28 28 29 class FFissionDecoder : public FFissionCodec … … 33 34 34 35 virtual void Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize); 36 virtual void Uninitialize(); 37 virtual void Reset(); 35 38 36 39 virtual void GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData); … … 41 44 virtual UInt32 GetVersion() const; 42 45 46 virtual void AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription); 43 47 virtual UInt32 ProduceOutputPackets(void* outOutputData, UInt32& ioOutputDataByteSize, UInt32& ioNumberPackets, AudioStreamPacketDescription* outPacketDescription); 44 48 … … 49 53 Byte *magicCookie; 50 54 UInt32 magicCookieSize; 55 56 RingBuffer inputBuffer; 57 Byte *outputBuffer; 58 int outBufSize; 59 int outBufUsed; 51 60 }; 52 61 trunk/Perian.xcodeproj/project.pbxproj
r406 r408 124 124 613CD51E0AD1FB650098A825 /* TextSubCodec.c in Sources */ = {isa = PBXBuildFile; fileRef = 613CD51A0AD1FB650098A825 /* TextSubCodec.c */; }; 125 125 613CD51F0AD1FB650098A825 /* TextSubCodec.r in Rez */ = {isa = PBXBuildFile; fileRef = 613CD51C0AD1FB650098A825 /* TextSubCodec.r */; }; 126 6156986F0BCDA87700E17ADE /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6156986D0BCDA87700E17ADE /* ringbuffer.cpp */; }; 126 127 61CB11200ACDF3A2007994BD /* Debug.h in Headers */ = {isa = PBXBuildFile; fileRef = 61CB11070ACDF3A2007994BD /* Debug.h */; }; 127 128 61CB11210ACDF3A2007994BD /* EbmlBinary.h in Headers */ = {isa = PBXBuildFile; fileRef = 61CB11080ACDF3A2007994BD /* EbmlBinary.h */; }; … … 514 515 613CD51C0AD1FB650098A825 /* TextSubCodec.r */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.rez; path = TextSubCodec.r; sourceTree = "<group>"; }; 515 516 613CD51D0AD1FB650098A825 /* TextSubCodecDispatch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TextSubCodecDispatch.h; sourceTree = "<group>"; }; 517 6156986D0BCDA87700E17ADE /* ringbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ringbuffer.cpp; sourceTree = "<group>"; }; 518 6156986E0BCDA87700E17ADE /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = "<group>"; }; 516 519 61CB10FF0ACDF350007994BD /* libebml.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libebml.a; sourceTree = BUILT_PRODUCTS_DIR; }; 517 520 61CB11070ACDF3A2007994BD /* Debug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Debug.h; path = libebml/ebml/Debug.h; sourceTree = "<group>"; }; … … 901 904 isa = PBXGroup; 902 905 children = ( 906 6156986D0BCDA87700E17ADE /* ringbuffer.cpp */, 907 6156986E0BCDA87700E17ADE /* ringbuffer.h */, 903 908 6116E54C0B43C27B0020F1CE /* FFissionCodec.cpp */, 904 909 6116E54D0B43C27B0020F1CE /* FFissionCodec.h */, … … 1593 1598 3DB2BB290B6C92F000416863 /* SSARenderCodec.m in Sources */, 1594 1599 3DAD32DA0B6DB26100DA0A72 /* StdIOCallback.cpp in Sources */, 1600 6156986F0BCDA87700E17ADE /* ringbuffer.cpp in Sources */, 1595 1601 ); 1596 1602 runOnlyForDeploymentPostprocessing = 0;
