shithub: openh264

Download patch

ref: 195df08bb9a0780ec3f567545ce384aded7b21c4
parent: 9b442b3d44bbb2afcdf0bea6e75191d4bacc8982
parent: 02365371e878b2134e0a098ed69e73d201862426
author: Ethan Hugg <ethanhugg@gmail.com>
date: Fri Jan 30 04:25:35 EST 2015

Merge pull request #1746 from kinetiknz/gmp-fixes

Various fixes for the GeckoMediaPlugin wrapper

--- a/module/gmp-openh264.cpp
+++ b/module/gmp-openh264.cpp
@@ -550,6 +550,16 @@
   FrameStats stats_;
 };
 
+uint16_t readU16BE(const uint8_t* in) {
+  return in[0] << 8 | in[1];
+}
+
+void copyWithStartCode(std::vector<uint8_t>& out, const uint8_t* in, size_t size) {
+  static const uint8_t code[] = { 0x00, 0x00, 0x00, 0x01 };
+  out.insert(out.end(), code, code + sizeof(code));
+  out.insert(out.end(), in, in + size);
+}
+
 class OpenH264VideoDecoder : public GMPVideoDecoder {
  public:
   OpenH264VideoDecoder (GMPVideoHost* hostAPI) :
@@ -595,6 +605,7 @@
     param.eOutputColorFormat = videoFormatI420;
     param.uiTargetDqLayer = UCHAR_MAX;  // Default value
     param.eEcActiveIdc = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE; // Error concealment on.
+    param.sVideoProperty.size = sizeof(param.sVideoProperty);
     param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
 
     if (decoder_->Initialize (&param)) {
@@ -602,6 +613,43 @@
       Error (GMPGenericErr);
       return;
     }
+
+    if (aCodecSpecific && aCodecSpecificSize >= sizeof(GMPVideoCodecH264)) {
+      std::vector<uint8_t> annexb;
+
+      // Convert the AVCC data, starting at the byte containing
+      // numOfSequenceParameterSets, to Annex B format.
+      const uint8_t* avcc = aCodecSpecific + offsetof(GMPVideoCodecH264, mAVCC.mNumSPS);
+
+      static const int kSPSMask = (1 << 5) - 1;
+      uint8_t spsCount = *avcc++ & kSPSMask;
+      for (int i = 0; i < spsCount; ++i) {
+        size_t size = readU16BE(avcc);
+        avcc += 2;
+        copyWithStartCode(annexb, avcc, size);
+        avcc += size;
+      }
+
+      uint8_t ppsCount = *avcc++;
+      for (int i = 0; i < ppsCount; ++i) {
+        size_t size = readU16BE(avcc);
+        avcc += 2;
+        copyWithStartCode(annexb, avcc, size);
+        avcc += size;
+      }
+
+      SBufferInfo decoded;
+      memset (&decoded, 0, sizeof (decoded));
+      unsigned char* data[3] = {nullptr, nullptr, nullptr};
+      DECODING_STATE dState = decoder_->DecodeFrame2 (&*annexb.begin(),
+                                                      annexb.size(),
+                                                      data,
+                                                      &decoded);
+      if (dState) {
+        GMPLOG (GL_ERROR, "Decoding error dState=" << dState);
+      }
+      GMPLOG (GL_ERROR, "InitDecode iBufferStatus=" << decoded.iBufferStatus);
+    }
   }
 
   virtual void Decode (GMPVideoEncodedFrame* inputFrame,
@@ -655,9 +703,15 @@
   }
 
   virtual void Reset() {
+    if (callback_) {
+      callback_->ResetComplete ();
+    }
   }
 
   virtual void Drain() {
+    if (callback_) {
+      callback_->DrainComplete ();
+    }
   }
 
   virtual void DecodingComplete() {
@@ -715,11 +769,14 @@
 
     // If we don't actually have data, just abort.
     if (!valid) {
+      GMPLOG (GL_ERROR, "No valid data decoded");
       Error (GMPDecodeErr);
       return;
     }
 
     if (decoded->iBufferStatus != 1) {
+      GMPLOG (GL_ERROR, "iBufferStatus=" << decoded->iBufferStatus);
+      callback_->InputDataExhausted();
       return;
     }