[xiph-commits] r11273 - in trunk/xiph-qt/CAVorbis: . src

arek at svn.xiph.org arek at svn.xiph.org
Mon Apr 24 15:28:54 PDT 2006


Author: arek
Date: 2006-04-24 15:28:46 -0700 (Mon, 24 Apr 2006)
New Revision: 11273

Modified:
   trunk/xiph-qt/CAVorbis/Info.plist
   trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.cpp
   trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.h
   trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.cpp
   trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.h
   trunk/xiph-qt/CAVorbis/src/vorbis_versions.h
Log:
Added support for non-zero sample offset on the first ogg page.
Also, applied some small changes suggested by Apple engineers (received
through Steve Nicolai!) regarding problems QT has with VBR codecs :P
Well, we'll see how it works...


Modified: trunk/xiph-qt/CAVorbis/Info.plist
===================================================================
--- trunk/xiph-qt/CAVorbis/Info.plist	2006-04-24 22:22:14 UTC (rev 11272)
+++ trunk/xiph-qt/CAVorbis/Info.plist	2006-04-24 22:28:46 UTC (rev 11273)
@@ -6,6 +6,8 @@
 	<string>English</string>
 	<key>CFBundleExecutable</key>
 	<string>CAVorbis</string>
+	<key>CFBundleGetInfoString</key>
+	<string>CoreAudio Vorbis Decoder Component 0.1.5, Copyright © 2005-2006 Arek Korbik</string>
 	<key>CFBundleIconFile</key>
 	<string></string>
 	<key>CFBundleIdentifier</key>
@@ -15,11 +17,13 @@
 	<key>CFBundlePackageType</key>
 	<string>BNDL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.1.1</string>
+	<string>0.1.5</string>
 	<key>CFBundleSignature</key>
 	<string>adec</string>
 	<key>CFBundleVersion</key>
-	<string>0.1.1</string>
+	<string>0.1.5</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>CoreAudio Vorbis Decoder Component 0.1.5, Copyright © 2005-2006 Arek Korbik</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
 </dict>

Modified: trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.cpp
===================================================================
--- trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.cpp	2006-04-24 22:22:14 UTC (rev 11272)
+++ trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.cpp	2006-04-24 22:28:46 UTC (rev 11273)
@@ -6,7 +6,7 @@
  *    for the actual decoding.
  *
  *
- *  Copyright (c) 2005  Arek Korbik
+ *  Copyright (c) 2005-2006  Arek Korbik
  *
  *  This file is part of XiphQT, the Xiph QuickTime Components.
  *
@@ -42,7 +42,12 @@
 
 CAOggVorbisDecoder::CAOggVorbisDecoder() :
     CAVorbisDecoder(true),
-    mFramesBufferedList()
+    mFramesBufferedList(),
+    mSOBuffer(NULL),
+    mSOBufferSize(0), mSOBufferUsed(0),
+    mSOBufferWrapped(0), mSOBufferPackets(0),
+    mSOBufferPages(0), mSOReturned(0),
+    mFirstPageNo(2)
 {
     CAStreamBasicDescription theInputFormat(kAudioStreamAnyRate, kAudioFormatXiphOggFramedVorbis,
                                             kVorbisBytesPerPacket, kVorbisFramesPerPacket,
@@ -50,7 +55,7 @@
                                             kVorbisBitsPerChannel, kVorbisFormatFlags);
     AddInputFormat(theInputFormat);
 
-    mInputFormat.mSampleRate = 44100;
+    mInputFormat.mSampleRate = 44100.0;
     mInputFormat.mFormatID = kAudioFormatXiphOggFramedVorbis;
     mInputFormat.mFormatFlags = kVorbisFormatFlags;
     mInputFormat.mBytesPerPacket = kVorbisBytesPerPacket;
@@ -67,7 +72,7 @@
                                               kAudioFormatFlagsNativeFloatPacked);
     AddOutputFormat(theOutputFormat2);
 
-    mOutputFormat.mSampleRate = 44100;
+    mOutputFormat.mSampleRate = 44100.0;
     mOutputFormat.mFormatID = kAudioFormatLinearPCM;
     mOutputFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
     mOutputFormat.mBytesPerPacket = 8;
@@ -81,6 +86,9 @@
 {
     if (mCompressionInitialized)
         ogg_stream_clear(&mO_st);
+
+    if (mSOBuffer)
+        delete[] mSOBuffer;
 }
 
 void CAOggVorbisDecoder::SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat)
@@ -99,7 +107,8 @@
 UInt32 CAOggVorbisDecoder::ProduceOutputPackets(void* outOutputData, UInt32& ioOutputDataByteSize, UInt32& ioNumberPackets,
                                                 AudioStreamPacketDescription* outPacketDescription)
 {
-    dbg_printf(" >> [%08lx] CAOggVorbisDecoder :: ProduceOutputPackets(%ld [%ld])\n", (UInt32) this, ioNumberPackets, ioOutputDataByteSize);
+    dbg_printf(" >> [%08lx] CAOggVorbisDecoder :: ProduceOutputPackets(%ld [%ld]) (%ld, %ld, %ld; %ld[%ld])\n",
+               (UInt32) this, ioNumberPackets, ioOutputDataByteSize, mSOBufferSize, mSOBufferUsed, mSOReturned, mSOBufferPages, mSOBufferPackets);
     UInt32 ret = kAudioCodecProduceOutputPacketSuccess;
 
     if (mFramesBufferedList.empty()) {
@@ -117,40 +126,133 @@
     UInt32 vorbis_total_returned_data = 0;
     Byte *the_data = static_cast<Byte*> (outOutputData);
 
-    while (true) {
-        UInt32 vorbis_return = CAVorbisDecoder::ProduceOutputPackets(the_data, vorbis_returned_data, vorbis_packets, NULL);
-        if (vorbis_return == kAudioCodecProduceOutputPacketSuccess || vorbis_return == kAudioCodecProduceOutputPacketSuccessHasMore) {
-            if (vorbis_packets > 0)
-                mFramesBufferedList.front() -= vorbis_packets;
+    if (mSOBuffer != NULL) {
+        dbg_printf("  + SOBuffering output\n");
+        /* stream/sample offset buffer not empty - must be beginning of the stream */
+        if (mSOBufferUsed == 0) {
+            /* fill the buffer first */
+            the_data = mSOBuffer;
+            vorbis_packets = mSOBufferPackets;
+            vorbis_returned_data = mSOBufferSize;
 
-            if (mFramesBufferedList.front() <= 0) {
-                ogg_packets++;
+            while (true) {
+                UInt32 vorbis_return = CAVorbisDecoder::ProduceOutputPackets(the_data, vorbis_returned_data, vorbis_packets, NULL);
+                if (vorbis_return == kAudioCodecProduceOutputPacketSuccess ||
+                    vorbis_return == kAudioCodecProduceOutputPacketSuccessHasMore ||
+                    vorbis_return == kAudioCodecProduceOutputPacketNeedsMoreInputData) {
+                    vorbis_total_returned_data += vorbis_returned_data;
+
+                    if (vorbis_return == kAudioCodecProduceOutputPacketSuccess || vorbis_return == kAudioCodecProduceOutputPacketNeedsMoreInputData)
+                    {
+                        /* ok, all data decoded */
+                        mSOBufferUsed = vorbis_total_returned_data;
+                        if (vorbis_total_returned_data > mSOBufferSize) {
+                            mSOBufferWrapped = vorbis_total_returned_data % mSOBufferSize;
+                            mSOBufferUsed = mSOBufferSize;
+                        } else if (vorbis_total_returned_data < mSOBufferSize) {
+                            BlockZero(mSOBuffer + mSOBufferUsed, mSOBufferSize - mSOBufferUsed);
+                            mSOBufferWrapped = mSOBufferUsed;
+                        }
+                        the_data = static_cast<Byte*> (outOutputData);
+                        break;
+                    } else {
+                        if (vorbis_total_returned_data < mSOBufferSize) {
+                            the_data += vorbis_returned_data;
+                            mSOBufferUsed = vorbis_total_returned_data;
+                            vorbis_returned_data = mSOBufferSize - mSOBufferUsed;
+                        } else {
+                            /* buffer filled, but the underlying decoder still has more... */
+                            the_data = mSOBuffer;
+                            mSOBufferUsed = mSOBufferSize;
+                            vorbis_returned_data = mSOBufferSize;
+                        }
+                        mSOBufferPackets -= vorbis_packets;
+                        vorbis_packets = mSOBufferPackets;
+                    }
+                } else {
+                    ret = kAudioCodecProduceOutputPacketFailure;
+                    ioOutputDataByteSize = 0;
+                    ioNumberPackets = mSOBufferPackets;
+                    break;
+                }
+            }
+        }
+
+        /* buffer filled, return chunk by chunk */
+        if (ret != kAudioCodecProduceOutputPacketFailure) {
+            vorbis_returned_data = mSOBufferSize - mSOReturned;
+            if (vorbis_returned_data > ioOutputDataByteSize)
+                vorbis_returned_data = ioOutputDataByteSize;
+            UInt32 offset = (mSOBufferWrapped + mSOReturned) % mSOBufferSize;
+            Byte *src_data = mSOBuffer + offset;
+            if (offset + vorbis_returned_data > mSOBufferSize) {
+                /* copy in two takes */
+                UInt32 first_chunk_size = mSOBufferSize - offset;
+                BlockMoveData(src_data, the_data, first_chunk_size);
+                BlockMoveData(mSOBuffer, the_data + first_chunk_size, vorbis_returned_data - first_chunk_size);
+            } else {
+                BlockMoveData(src_data, the_data, vorbis_returned_data);
+            }
+            mSOReturned += vorbis_returned_data;
+            ioOutputDataByteSize = vorbis_returned_data;
+            // ioNumberPackets = ioNumberPackets;
+            if (mSOReturned == mSOBufferSize) {
+                /* all data flushed */
+                ret = kAudioCodecProduceOutputPacketSuccess;
+                ioNumberPackets = mSOBufferPages;
                 mFramesBufferedList.erase(mFramesBufferedList.begin());
+                delete[] mSOBuffer;
+                mSOBufferSize = mSOBufferUsed = mSOBufferWrapped = mSOBufferPackets = mSOBufferPages = mSOReturned = 0;
+                mSOBuffer = NULL;
+            } else {
+                ret = kAudioCodecProduceOutputPacketSuccessHasMore;
+                ogg_packets = ioNumberPackets;
+                if (ogg_packets >= mSOBufferPages) {
+                    ogg_packets = 1;
+                }
+                if (mSOBufferPages == 1)
+                    ogg_packets = 0;
+                mSOBufferPages -= ogg_packets;
+                ioNumberPackets = ogg_packets;
             }
+        }
+    } else {
+        /* normal output without additional buffering */
+        while (true) {
+            UInt32 vorbis_return = CAVorbisDecoder::ProduceOutputPackets(the_data, vorbis_returned_data, vorbis_packets, NULL);
+            if (vorbis_return == kAudioCodecProduceOutputPacketSuccess || vorbis_return == kAudioCodecProduceOutputPacketSuccessHasMore) {
+                if (vorbis_packets > 0)
+                    mFramesBufferedList.front() -= vorbis_packets;
 
-            vorbis_total_returned_data += vorbis_returned_data;
+                if (mFramesBufferedList.front() <= 0) {
+                    ogg_packets++;
+                    mFramesBufferedList.erase(mFramesBufferedList.begin());
+                }
 
-            if (vorbis_total_returned_data == ioOutputDataByteSize || vorbis_return == kAudioCodecProduceOutputPacketSuccess)
-            {
-                ioNumberPackets = ogg_packets;
-                ioOutputDataByteSize = vorbis_total_returned_data;
+                vorbis_total_returned_data += vorbis_returned_data;
 
-                if (!mFramesBufferedList.empty())
-                    ret = kAudioCodecProduceOutputPacketSuccessHasMore;
-                else
-                    ret = kAudioCodecProduceOutputPacketSuccess;
+                if (vorbis_total_returned_data == ioOutputDataByteSize || vorbis_return == kAudioCodecProduceOutputPacketSuccess)
+                {
+                    ioNumberPackets = ogg_packets;
+                    ioOutputDataByteSize = vorbis_total_returned_data;
 
+                    if (!mFramesBufferedList.empty())
+                        ret = kAudioCodecProduceOutputPacketSuccessHasMore;
+                    else
+                        ret = kAudioCodecProduceOutputPacketSuccess;
+
+                    break;
+                } else {
+                    the_data += vorbis_returned_data;
+                    vorbis_returned_data = ioOutputDataByteSize - vorbis_total_returned_data;
+                    vorbis_packets = mFramesBufferedList.front();
+                }
+            } else {
+                ret = kAudioCodecProduceOutputPacketFailure;
+                ioOutputDataByteSize = vorbis_total_returned_data;
+                ioNumberPackets = ogg_packets;
                 break;
-            } else {
-                the_data += vorbis_returned_data;
-                vorbis_returned_data = ioOutputDataByteSize - vorbis_total_returned_data;
-                vorbis_packets = mFramesBufferedList.front();
             }
-        } else {
-            ret = kAudioCodecProduceOutputPacketFailure;
-            ioOutputDataByteSize = vorbis_total_returned_data;
-            ioNumberPackets = ogg_packets;
-            break;
         }
     }
 
@@ -168,12 +270,22 @@
 void CAOggVorbisDecoder::BDCUninitialize()
 {
     mFramesBufferedList.clear();
+
+    delete[] mSOBuffer;
+    mSOBufferSize = mSOBufferUsed = mSOBufferWrapped = mSOBufferPackets = mSOBufferPages = mSOReturned = 0;
+    mSOBuffer = NULL;
+
     CAVorbisDecoder::BDCUninitialize();
 }
 
 void CAOggVorbisDecoder::BDCReset()
 {
     mFramesBufferedList.clear();
+
+    delete[] mSOBuffer;
+    mSOBufferSize = mSOBufferUsed = mSOBufferWrapped = mSOBufferPackets = mSOBufferPages = mSOReturned = 0;
+    mSOBuffer = NULL;
+
     if (mCompressionInitialized)
         ogg_stream_reset(&mO_st);
     CAVorbisDecoder::BDCReset();
@@ -188,6 +300,7 @@
 
 void CAOggVorbisDecoder::InPacket(const void* inInputData, const AudioStreamPacketDescription* inPacketDescription)
 {
+    dbg_printf(" >> [%08lx] CAOggVorbisDecoder :: InPacket({%ld, %ld})\n", (UInt32) this, inPacketDescription->mDataByteSize, inPacketDescription->mVariableFramesInPacket);
     if (!mCompressionInitialized)
         CODEC_THROW(kAudioCodecUnspecifiedError);
 
@@ -217,6 +330,26 @@
     }
 
     mFramesBufferedList.push_back(packet_count);
+
+    /* if pageno == FPN from the cookie then this is the first audio page
+       - we need to buffer the audio data from the first page, to be able
+       to apply the stream offset described in Vorbis spec, section A.2 */
+    /* the expected number of audio samples(frames) should be less than
+       some reasonable value, like 255 * 8192:
+       (max packets per ogg page * max size of a vorbis block) */
+    if (ogg_page_pageno(&op) == mFirstPageNo && inPacketDescription->mVariableFramesInPacket > 0 && inPacketDescription->mVariableFramesInPacket < (255 * 8192)) {
+        mSOBufferSize = inPacketDescription->mVariableFramesInPacket * mOutputFormat.mBytesPerFrame;
+        if (mSOBuffer)
+            delete[] mSOBuffer;
+        mSOBuffer = new Byte[mSOBufferSize];
+        mSOBufferUsed = 0;
+        mSOBufferWrapped = 0;
+        mSOBufferPackets = packet_count;
+        mSOBufferPages = 1; // ?! :/
+        mSOReturned = 0;
+    }
+
+    dbg_printf("<.. [%08lx] CAOggVorbisDecoder :: InPacket(pn: %ld)\n", (UInt32) this, ogg_page_pageno (&op));
 }
 
 
@@ -227,10 +360,24 @@
             ogg_stream_clear(&mO_st);
 
         OggSerialNoAtom *atom = reinterpret_cast<OggSerialNoAtom*> (mCookie);
+        Byte *ptrheader = mCookie + EndianU32_BtoN(atom->size);
+        Byte *cend = mCookie + mCookieSize;
+        CookieAtomHeader *aheader = reinterpret_cast<CookieAtomHeader*> (ptrheader);
 
         if (EndianS32_BtoN(atom->type) == kCookieTypeOggSerialNo && EndianS32_BtoN(atom->size) <= mCookieSize) {
             ogg_stream_init(&mO_st, EndianS32_BtoN(atom->serialno));
         }
+
+        while (ptrheader < cend) {
+            aheader = reinterpret_cast<CookieAtomHeader*> (ptrheader);
+            ptrheader += EndianU32_BtoN(aheader->size);
+
+            if (EndianS32_BtoN(aheader->type) == kCookieTypeVorbisFirstPageNo && ptrheader <= cend) {
+                mFirstPageNo = EndianU32_BtoN((reinterpret_cast<OggSerialNoAtom*> (aheader))->serialno);
+                dbg_printf("  = [%08lx] CAOggVorbisDecoder :: InitializeCompressionSettings(fpn: %ld)\n", (UInt32) this, mFirstPageNo);
+                break;
+            }
+        }
     }
 
     ogg_stream_reset(&mO_st);

Modified: trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.h
===================================================================
--- trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.h	2006-04-24 22:22:14 UTC (rev 11272)
+++ trunk/xiph-qt/CAVorbis/src/CAOggVorbisDecoder.h	2006-04-24 22:28:46 UTC (rev 11273)
@@ -4,7 +4,7 @@
  *    CAOggVorbisDecoder class definition.
  *
  *
- *  Copyright (c) 2005  Arek Korbik
+ *  Copyright (c) 2005-2006  Arek Korbik
  *
  *  This file is part of XiphQT, the Xiph QuickTime Components.
  *
@@ -62,6 +62,17 @@
 
     ogg_stream_state        mO_st;
     std::vector<SInt32>     mFramesBufferedList;
+
+    /* SampleOffsetBuffer */
+    Byte                    *mSOBuffer;
+    UInt32                  mSOBufferSize;
+    UInt32                  mSOBufferUsed;
+    UInt32                  mSOBufferWrapped;
+    UInt32                  mSOBufferPackets;
+    UInt32                  mSOBufferPages;
+    UInt32                  mSOReturned;
+
+    UInt32                  mFirstPageNo;
 };
 
 

Modified: trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.cpp
===================================================================
--- trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.cpp	2006-04-24 22:22:14 UTC (rev 11272)
+++ trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.cpp	2006-04-24 22:28:46 UTC (rev 11273)
@@ -5,7 +5,7 @@
  *    codec functionality.
  *
  *
- *  Copyright (c) 2005  Arek Korbik
+ *  Copyright (c) 2005-2006  Arek Korbik
  *
  *  This file is part of XiphQT, the Xiph QuickTime Components.
  *
@@ -57,7 +57,7 @@
                                             kVorbisBitsPerChannel, kVorbisFormatFlags);
     AddInputFormat(theInputFormat);
 
-    mInputFormat.mSampleRate = 44100;
+    mInputFormat.mSampleRate = 44100.0;
     mInputFormat.mFormatID = kAudioFormatXiphVorbis;
     mInputFormat.mFormatFlags = kVorbisFormatFlags;
     mInputFormat.mBytesPerPacket = kVorbisBytesPerPacket;
@@ -74,7 +74,7 @@
                                               kAudioFormatFlagsNativeFloatPacked);
     AddOutputFormat(theOutputFormat2);
 
-    mOutputFormat.mSampleRate = 44100;
+    mOutputFormat.mSampleRate = 44100.0;
     mOutputFormat.mFormatID = kAudioFormatLinearPCM;
     mOutputFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
     mOutputFormat.mBytesPerPacket = 8;
@@ -169,7 +169,15 @@
     case kAudioCodecPropertyPacketFrameSize:
         if(ioPropertyDataSize == sizeof(UInt32))
         {
-            *reinterpret_cast<UInt32*>(outPropertyData) = kVorbisFramesPerPacket;
+            /* The following line has been changed according to Apple engineers' suggestion
+               I received via Steve Nicolai (in response to *my* bugreport, I think...).
+                 (Why don't they just implement the VBR-VFPP properly? *sigh*)
+
+               The original line is left here as I still believe that's how it should be
+               implemented according to the QT docs. (And in case this workaround stops
+               working again one wonderful morning!) */
+            // *reinterpret_cast<UInt32*>(outPropertyData) = kVorbisFramesPerPacket;
+            *reinterpret_cast<UInt32*>(outPropertyData) = kVorbisFramesPerPacketReported;
         }
         else
         {
@@ -177,6 +185,14 @@
         }
         break;
 
+    case kAudioCodecPropertyMaximumPacketByteSize:
+        if(ioPropertyDataSize == sizeof(UInt32)) {
+            *reinterpret_cast<UInt32*>(outPropertyData) = kVorbisFormatMaxBytesPerPacket;
+        } else {
+            CODEC_THROW(kAudioCodecBadPropertySizeError);
+        }
+        break;
+
         //case kAudioCodecPropertyQualitySetting: ???
 #if TARGET_OS_MAC
     case kAudioCodecPropertyNameCFString:
@@ -217,6 +233,11 @@
         outWritable = false;
         break;
 
+    case kAudioCodecPropertyMaximumPacketByteSize:
+        outPropertyDataSize = sizeof(UInt32);
+        outWritable = false;
+        break;
+
     default:
         ACBaseCodec::GetPropertyInfo(inPropertyID, outPropertyDataSize, outWritable);
         break;

Modified: trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.h
===================================================================
--- trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.h	2006-04-24 22:22:14 UTC (rev 11272)
+++ trunk/xiph-qt/CAVorbis/src/CAVorbisDecoder.h	2006-04-24 22:28:46 UTC (rev 11273)
@@ -120,11 +120,15 @@
     enum {
         kVorbisBytesPerPacket = 0,
         kVorbisFramesPerPacket = _SHOULD_BE_ZERO_HERE,
+        kVorbisFramesPerPacketReported = 8192,
         kVorbisBytesPerFrame = 0,
         kVorbisChannelsPerFrame = 0,
         kVorbisBitsPerChannel = 16,
         kVorbisFormatFlags = 0,
 
+        /* Just a funny number, and only roughly valid for the 'Xiph (Ogg-Framed) Vorbis'. */
+        kVorbisFormatMaxBytesPerPacket = 255 * 255,
+
         kVorbisDecoderBufferSize = 64 * 1024
     };
 };

Modified: trunk/xiph-qt/CAVorbis/src/vorbis_versions.h
===================================================================
--- trunk/xiph-qt/CAVorbis/src/vorbis_versions.h	2006-04-24 22:22:14 UTC (rev 11272)
+++ trunk/xiph-qt/CAVorbis/src/vorbis_versions.h	2006-04-24 22:28:46 UTC (rev 11273)
@@ -4,7 +4,7 @@
  *    The current version of the Vorbis component.
  *
  *
- *  Copyright (c) 2005  Arek Korbik
+ *  Copyright (c) 2005-2006  Arek Korbik
  *
  *  This file is part of XiphQT, the Xiph QuickTime Components.
  *
@@ -33,9 +33,9 @@
 
 
 #ifdef DEBUG
-#define kCAVorbis_adec_Version		(0x00FF0101)
+#define kCAVorbis_adec_Version		(0x00FF0105)
 #else
-#define kCAVorbis_adec_Version		(0x00000101)
+#define kCAVorbis_adec_Version		(0x00000105)
 #endif /* DEBUG */
 
 



More information about the commits mailing list