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 (¶m)) {
@@ -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;
}