Merge "Add ABuffer support to SkipCutBuffer"
diff --git a/include/media/stagefright/SkipCutBuffer.h b/include/media/stagefright/SkipCutBuffer.h
index 5c7cd47..27851ca 100644
--- a/include/media/stagefright/SkipCutBuffer.h
+++ b/include/media/stagefright/SkipCutBuffer.h
@@ -19,6 +19,7 @@
 #define SKIP_CUT_BUFFER_H_
 
 #include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/foundation/ABuffer.h>
 
 namespace android {
 
@@ -30,14 +31,14 @@
  public:
     // 'skip' is the number of bytes to skip from the beginning
     // 'cut' is the number of bytes to cut from the end
-    // 'output_size' is the size in bytes of the MediaBuffers that will be used
-    SkipCutBuffer(int32_t skip, int32_t cut, int32_t output_size);
+    SkipCutBuffer(int32_t skip, int32_t cut);
     virtual ~SkipCutBuffer();
 
     // Submit one MediaBuffer for skipping and cutting. This may consume all or
     // some of the data in the buffer, or it may add data to it.
     // After this, the caller should continue processing the buffer as usual.
     void submit(MediaBuffer *buffer);
+    void submit(const sp<ABuffer>& buffer);    // same as above, but with an ABuffer
     void clear();
     size_t size(); // how many bytes are currently stored in the buffer
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 9769f21..d9ad525 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1605,8 +1605,7 @@
                     }
                     delete mSkipCutBuffer;
                 }
-                mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize,
-                                                   def.nBufferSize);
+                mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize);
             }
         }
     }
diff --git a/media/libstagefright/SkipCutBuffer.cpp b/media/libstagefright/SkipCutBuffer.cpp
index 6d331b0..773854f 100755
--- a/media/libstagefright/SkipCutBuffer.cpp
+++ b/media/libstagefright/SkipCutBuffer.cpp
@@ -24,12 +24,12 @@
 
 namespace android {
 
-SkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut, int32_t output_size) {
+SkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut) {
     mFrontPadding = skip;
     mBackPadding = cut;
     mWriteHead = 0;
     mReadHead = 0;
-    mCapacity = cut + output_size;
+    mCapacity = cut + 4096;
     mCutBuffer = new char[mCapacity];
     ALOGV("skipcutbuffer %d %d %d", skip, cut, mCapacity);
 }
@@ -65,6 +65,33 @@
     buffer->set_range(0, copied);
 }
 
+void SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
+    int32_t offset = buffer->offset();
+    int32_t buflen = buffer->size();
+
+    // drop the initial data from the buffer if needed
+    if (mFrontPadding > 0) {
+        // still data left to drop
+        int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
+        offset += to_drop;
+        buflen -= to_drop;
+        buffer->setRange(offset, buflen);
+        mFrontPadding -= to_drop;
+    }
+
+
+    // append data to cutbuffer
+    char *src = (char*) buffer->data();
+    write(src, buflen);
+
+
+    // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
+    // at least mBackPadding bytes in the cutbuffer
+    char *dst = (char*) buffer->base();
+    size_t copied = read(dst, buffer->capacity());
+    buffer->setRange(0, copied);
+}
+
 void SkipCutBuffer::clear() {
     mWriteHead = mReadHead = 0;
 }
@@ -73,8 +100,19 @@
     int32_t sizeused = (mWriteHead - mReadHead);
     if (sizeused < 0) sizeused += mCapacity;
 
-    // everything must fit
-    CHECK_GE((mCapacity - size_t(sizeused)), num);
+    // Everything must fit. Make sure the buffer is a little larger than needed,
+    // so there is no ambiguity as to whether mWriteHead == mReadHead means buffer
+    // full or empty
+    size_t available = mCapacity - sizeused - 32;
+    if (available < num) {
+        int32_t newcapacity = mCapacity + (num - available);
+        char * newbuffer = new char[newcapacity];
+        memcpy(newbuffer, mCutBuffer, mCapacity);
+        delete [] mCutBuffer;
+        mCapacity = newcapacity;
+        mCutBuffer = newbuffer;
+        ALOGV("reallocated buffer at size %d", newcapacity);
+    }
 
     size_t copyfirst = (mCapacity - mWriteHead);
     if (copyfirst > num) copyfirst = num;
@@ -100,7 +138,7 @@
     if (available <=0) {
         return 0;
     }
-    if (available < num) {
+    if (available < int32_t(num)) {
         num = available;
     }