ref: 9ea66030719c2f0911b05cbcc79f9af89548eea8
parent: 30d7352d03ab9a5b07d7c94ad823020a27947459
author: Matthew Gregan <kinetik@flim.org>
date: Tue Jan 13 14:00:18 EST 2015
Pass AVCC extra data to the decoder (in AnnexB format) in InitDecode.
--- a/module/gmp-openh264.cpp
+++ b/module/gmp-openh264.cpp
@@ -548,6 +548,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) :
@@ -599,6 +609,43 @@
GMPLOG (GL_ERROR, "Couldn't initialize decoder");
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);
}
}