Merge pull request #1155 from ethanhugg/gmpapi-ff33

Updated to match gmp-api changes for Firefox33
This commit is contained in:
Ethan Hugg 2014-07-11 12:00:06 -07:00
commit d49e7208fb
3 changed files with 101 additions and 62 deletions

View File

@ -17,7 +17,7 @@ SHARED=-shared
OBJ=o OBJ=o
PROJECT_NAME=openh264 PROJECT_NAME=openh264
MODULE_NAME=gmpopenh264 MODULE_NAME=gmpopenh264
GMP_API_BRANCH=Firefox32 GMP_API_BRANCH=master
CCASFLAGS=$(CFLAGS) CCASFLAGS=$(CFLAGS)
ifeq (,$(wildcard ./gmp-api)) ifeq (,$(wildcard ./gmp-api))

View File

@ -190,19 +190,21 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
worker_thread_->Join(); worker_thread_->Join();
} }
virtual GMPVideoErr InitEncode (const GMPVideoCodec& codecSettings, virtual GMPErr InitEncode (const GMPVideoCodec& codecSettings,
GMPEncoderCallback* callback, const uint8_t* aCodecSpecific,
uint32_t aCodecSpecificSize,
GMPVideoEncoderCallback* callback,
int32_t numberOfCores, int32_t numberOfCores,
uint32_t maxPayloadSize) { uint32_t maxPayloadSize) {
GMPErr err = g_platform_api->createthread (&worker_thread_); GMPErr err = g_platform_api->createthread (&worker_thread_);
if (err != GMPNoErr) { if (err != GMPNoErr) {
GMPLOG (GL_ERROR, "Couldn't create new thread"); GMPLOG (GL_ERROR, "Couldn't create new thread");
return GMPVideoGenericErr; return GMPGenericErr;
} }
int rv = WelsCreateSVCEncoder (&encoder_); int rv = WelsCreateSVCEncoder (&encoder_);
if (rv) { if (rv) {
return GMPVideoGenericErr; return GMPGenericErr;
} }
SEncParamBase param; SEncParamBase param;
@ -236,7 +238,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
rv = encoder_->Initialize (&param); rv = encoder_->Initialize (&param);
if (rv) { if (rv) {
GMPLOG (GL_ERROR, "Couldn't initialize encoder"); GMPLOG (GL_ERROR, "Couldn't initialize encoder");
return GMPVideoGenericErr; return GMPGenericErr;
} }
max_payload_size_ = maxPayloadSize; max_payload_size_ = maxPayloadSize;
@ -244,12 +246,14 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
GMPLOG (GL_INFO, "Initialized encoder"); GMPLOG (GL_INFO, "Initialized encoder");
return GMPVideoNoErr; return GMPNoErr;
} }
virtual GMPVideoErr Encode (GMPVideoi420Frame* inputImage, virtual GMPErr Encode (GMPVideoi420Frame* inputImage,
const GMPCodecSpecificInfo& codecSpecificInfo, const uint8_t* aCodecSpecificInfo,
const std::vector<GMPVideoFrameType>& frameTypes) { uint32_t aCodecSpecificInfoLength,
const GMPVideoFrameType* aFrameTypes,
uint32_t aFrameTypesLength) {
GMPLOG (GL_DEBUG, GMPLOG (GL_DEBUG,
__FUNCTION__ __FUNCTION__
<< " size=" << " size="
@ -257,19 +261,14 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
stats_.FrameIn(); stats_.FrameIn();
assert (!frameTypes.empty()); assert (aFrameTypesLength != 0);
if (frameTypes.empty()) {
GMPLOG (GL_ERROR, "No frame types provided");
inputImage->Destroy();
return GMPVideoGenericErr;
}
worker_thread_->Post (WrapTask ( worker_thread_->Post (WrapTask (
this, &OpenH264VideoEncoder::Encode_w, this, &OpenH264VideoEncoder::Encode_w,
inputImage, inputImage,
(frameTypes)[0])); (aFrameTypes)[0]));
return GMPVideoGenericErr; return GMPGenericErr;
} }
void Encode_w (GMPVideoi420Frame* inputImage, void Encode_w (GMPVideoi420Frame* inputImage,
@ -363,8 +362,8 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
GMPVideoFrameType frame_type) { GMPVideoFrameType frame_type) {
// Now return the encoded data back to the parent. // Now return the encoded data back to the parent.
GMPVideoFrame* ftmp; GMPVideoFrame* ftmp;
GMPVideoErr err = host_->CreateFrame (kGMPEncodedVideoFrame, &ftmp); GMPErr err = host_->CreateFrame (kGMPEncodedVideoFrame, &ftmp);
if (err != GMPVideoNoErr) { if (err != GMPNoErr) {
GMPLOG (GL_ERROR, "Error creating encoded frame"); GMPLOG (GL_ERROR, "Error creating encoded frame");
frame->Destroy(); frame->Destroy();
return; return;
@ -377,17 +376,20 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
for (int i = 0; i < encoded->iLayerNum; ++i) { for (int i = 0; i < encoded->iLayerNum; ++i) {
lengths.push_back (0); lengths.push_back (0);
uint8_t* tmp = encoded->sLayerInfo[i].pBsBuf;
for (int j = 0; j < encoded->sLayerInfo[i].iNalCount; ++j) { for (int j = 0; j < encoded->sLayerInfo[i].iNalCount; ++j) {
lengths[i] += encoded->sLayerInfo[i].pNalLengthInByte[j]; lengths[i] += encoded->sLayerInfo[i].pNalLengthInByte[j];
// Convert from 4-byte start codes to GMP_BufferLength32 (NAL lengths)
assert (* (reinterpret_cast<uint32_t*> (tmp)) == 0x01000000);
// BufferType32 doesn't include the length of the length itself!
* (reinterpret_cast<uint32_t*> (tmp)) = encoded->sLayerInfo[i].pNalLengthInByte[j] - sizeof (uint32_t);
length += encoded->sLayerInfo[i].pNalLengthInByte[j]; length += encoded->sLayerInfo[i].pNalLengthInByte[j];
tmp += encoded->sLayerInfo[i].pNalLengthInByte[j];
} }
} }
// TODO start-code to length conversion here when gmp
// stops doing it for us before this call.
err = f->CreateEmptyFrame (length); err = f->CreateEmptyFrame (length);
if (err != GMPVideoNoErr) { if (err != GMPNoErr) {
GMPLOG (GL_ERROR, "Error allocating frame data"); GMPLOG (GL_ERROR, "Error allocating frame data");
f->Destroy(); f->Destroy();
frame->Destroy(); frame->Destroy();
@ -407,6 +409,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
f->SetTimeStamp (frame->Timestamp()); f->SetTimeStamp (frame->Timestamp());
f->SetFrameType (frame_type); f->SetFrameType (frame_type);
f->SetCompleteFrame (true); f->SetCompleteFrame (true);
f->SetBufferType (GMP_BufferLength32);
GMPLOG (GL_DEBUG, "Encoding complete. type= " GMPLOG (GL_DEBUG, "Encoding complete. type= "
<< f->FrameType() << f->FrameType()
@ -420,9 +423,12 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
// Return the encoded frame. // Return the encoded frame.
GMPCodecSpecificInfo info; GMPCodecSpecificInfo info;
memset (&info, 0, sizeof (info)); memset (&info, 0, sizeof (info)); // shouldn't be needed, we init everything
// TODO need to set what goes in this info structure. info.mCodecType = kGMPVideoCodecH264;
callback_->Encoded (f, info); info.mBufferType = GMP_BufferLength32;
info.mCodecSpecific.mH264.mSimulcastIdx = 0;
callback_->Encoded (f, reinterpret_cast<uint8_t*> (&info), sizeof (info));
stats_.FrameOut(); stats_.FrameOut();
} }
@ -432,11 +438,11 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
frame->Destroy(); frame->Destroy();
} }
virtual GMPVideoErr SetChannelParameters (uint32_t aPacketLoss, uint32_t aRTT) { virtual GMPErr SetChannelParameters (uint32_t aPacketLoss, uint32_t aRTT) {
return GMPVideoNoErr; return GMPNoErr;
} }
virtual GMPVideoErr SetRates (uint32_t aNewBitRate, uint32_t aFrameRate) { virtual GMPErr SetRates (uint32_t aNewBitRate, uint32_t aFrameRate) {
GMPLOG (GL_INFO, "[SetRates] Begin with: " GMPLOG (GL_INFO, "[SetRates] Begin with: "
<< aNewBitRate << " , " << aFrameRate); << aNewBitRate << " , " << aFrameRate);
//update bitrate if needed //update bitrate if needed
@ -451,7 +457,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
<< existEncoderBitRate.iLayer << existEncoderBitRate.iLayer
<< " ; BR = " << " ; BR = "
<< existEncoderBitRate.iBitrate); << existEncoderBitRate.iBitrate);
return GMPVideoGenericErr; return GMPGenericErr;
} }
if (rv == cmResultSuccess && existEncoderBitRate.iBitrate != newBitRate) { if (rv == cmResultSuccess && existEncoderBitRate.iBitrate != newBitRate) {
SBitrateInfo newEncoderBitRate; SBitrateInfo newEncoderBitRate;
@ -470,7 +476,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
<< newEncoderBitRate.iLayer << newEncoderBitRate.iLayer
<< " ; BR = " << " ; BR = "
<< newEncoderBitRate.iBitrate); << newEncoderBitRate.iBitrate);
return GMPVideoGenericErr; return GMPGenericErr;
} }
} }
//update framerate if needed //update framerate if needed
@ -479,7 +485,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
if (rv != cmResultSuccess) { if (rv != cmResultSuccess) {
GMPLOG (GL_ERROR, "[SetRates] Error in Getting Frame Rate:" GMPLOG (GL_ERROR, "[SetRates] Error in Getting Frame Rate:"
<< rv << " FrameRate: " << existFrameRate); << rv << " FrameRate: " << existFrameRate);
return GMPVideoGenericErr; return GMPGenericErr;
} }
if (rv == cmResultSuccess && if (rv == cmResultSuccess &&
(aFrameRate - existFrameRate > 0.001f || (aFrameRate - existFrameRate > 0.001f ||
@ -492,14 +498,14 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
} else { } else {
GMPLOG (GL_ERROR, "[SetRates] Error in Setting Frame Rate: ReturnValue: " GMPLOG (GL_ERROR, "[SetRates] Error in Setting Frame Rate: ReturnValue: "
<< rv << " FrameRate: " << aFrameRate); << rv << " FrameRate: " << aFrameRate);
return GMPVideoGenericErr; return GMPGenericErr;
} }
} }
return GMPVideoNoErr; return GMPNoErr;
} }
virtual GMPVideoErr SetPeriodicKeyFrames (bool aEnable) { virtual GMPErr SetPeriodicKeyFrames (bool aEnable) {
return GMPVideoNoErr; return GMPNoErr;
} }
virtual void EncodingComplete() { virtual void EncodingComplete() {
@ -511,7 +517,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
GMPThread* worker_thread_; GMPThread* worker_thread_;
ISVCEncoder* encoder_; ISVCEncoder* encoder_;
uint32_t max_payload_size_; uint32_t max_payload_size_;
GMPEncoderCallback* callback_; GMPVideoEncoderCallback* callback_;
FrameStats stats_; FrameStats stats_;
}; };
@ -527,25 +533,27 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
virtual ~OpenH264VideoDecoder() { virtual ~OpenH264VideoDecoder() {
} }
virtual GMPVideoErr InitDecode (const GMPVideoCodec& codecSettings, virtual GMPErr InitDecode (const GMPVideoCodec& codecSettings,
GMPDecoderCallback* callback, const uint8_t* aCodecSpecific,
uint32_t aCodecSpecificSize,
GMPVideoDecoderCallback* callback,
int32_t coreCount) { int32_t coreCount) {
GMPLOG (GL_INFO, "InitDecode"); GMPLOG (GL_INFO, "InitDecode");
GMPErr err = g_platform_api->createthread (&worker_thread_); GMPErr err = g_platform_api->createthread (&worker_thread_);
if (err != GMPNoErr) { if (err != GMPNoErr) {
GMPLOG (GL_ERROR, "Couldn't create new thread"); GMPLOG (GL_ERROR, "Couldn't create new thread");
return GMPVideoGenericErr; return GMPGenericErr;
} }
if (WelsCreateDecoder (&decoder_)) { if (WelsCreateDecoder (&decoder_)) {
GMPLOG (GL_ERROR, "Couldn't create decoder"); GMPLOG (GL_ERROR, "Couldn't create decoder");
return GMPVideoGenericErr; return GMPGenericErr;
} }
if (!decoder_) { if (!decoder_) {
GMPLOG (GL_ERROR, "Couldn't create decoder"); GMPLOG (GL_ERROR, "Couldn't create decoder");
return GMPVideoGenericErr; return GMPGenericErr;
} }
SDecodingParam param; SDecodingParam param;
@ -557,21 +565,49 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
if (decoder_->Initialize (&param)) { if (decoder_->Initialize (&param)) {
GMPLOG (GL_ERROR, "Couldn't initialize decoder"); GMPLOG (GL_ERROR, "Couldn't initialize decoder");
return GMPVideoGenericErr; return GMPGenericErr;
} }
callback_ = callback; callback_ = callback;
return GMPVideoNoErr; return GMPNoErr;
} }
virtual GMPVideoErr Decode (GMPVideoEncodedFrame* inputFrame, virtual GMPErr Decode (GMPVideoEncodedFrame* inputFrame,
bool missingFrames, bool missingFrames,
const GMPCodecSpecificInfo& codecSpecificInfo, const uint8_t* aCodecSpecificInfo,
uint32_t aCodecSpecificInfoLength,
int64_t renderTimeMs = -1) { int64_t renderTimeMs = -1) {
GMPLOG (GL_DEBUG, __FUNCTION__ GMPLOG (GL_DEBUG, __FUNCTION__
<< "Decoding frame size=" << inputFrame->Size() << "Decoding frame size=" << inputFrame->Size()
<< " timestamp=" << inputFrame->TimeStamp()); << " timestamp=" << inputFrame->TimeStamp());
stats_.FrameIn(); stats_.FrameIn();
//const GMPCodecSpecificInfo *codecSpecificInfo = (GMPCodecSpecificInfo) aCodecSpecificInfo;
// Convert to H.264 start codes
switch (inputFrame->BufferType()) {
case GMP_BufferSingle:
case GMP_BufferLength8:
case GMP_BufferLength16:
case GMP_BufferLength24:
// We should look to support these, especially GMP_BufferSingle
assert (false);
break;
case GMP_BufferLength32: {
uint8_t* start_code = inputFrame->Buffer();
while (start_code < inputFrame->Buffer() + inputFrame->Size()) {
static const uint8_t code[] = { 0x00, 0x00, 0x00, 0x01 };
uint8_t* lenp = start_code;
start_code += * (reinterpret_cast<int32_t*> (lenp));
memcpy (lenp, code, 4);
}
}
break;
default:
assert (false);
break;
}
worker_thread_->Post (WrapTask ( worker_thread_->Post (WrapTask (
this, &OpenH264VideoDecoder::Decode_w, this, &OpenH264VideoDecoder::Decode_w,
@ -579,15 +615,15 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
missingFrames, missingFrames,
renderTimeMs)); renderTimeMs));
return GMPVideoNoErr; return GMPNoErr;
} }
virtual GMPVideoErr Reset() { virtual GMPErr Reset() {
return GMPVideoNoErr; return GMPNoErr;
} }
virtual GMPVideoErr Drain() { virtual GMPErr Drain() {
return GMPVideoNoErr; return GMPNoErr;
} }
virtual void DecodingComplete() { virtual void DecodingComplete() {
@ -660,8 +696,8 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
GMPVideoFrame* ftmp = nullptr; GMPVideoFrame* ftmp = nullptr;
// Translate the image. // Translate the image.
GMPVideoErr err = host_->CreateFrame (kGMPI420VideoFrame, &ftmp); GMPErr err = host_->CreateFrame (kGMPI420VideoFrame, &ftmp);
if (err != GMPVideoNoErr) { if (err != GMPNoErr) {
GMPLOG (GL_ERROR, "Couldn't allocate empty I420 frame"); GMPLOG (GL_ERROR, "Couldn't allocate empty I420 frame");
return; return;
} }
@ -674,7 +710,7 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
uvstride * height / 2, static_cast<uint8_t*> (data[2]), uvstride * height / 2, static_cast<uint8_t*> (data[2]),
width, height, width, height,
ystride, uvstride, uvstride); ystride, uvstride, uvstride);
if (err != GMPVideoNoErr) { if (err != GMPNoErr) {
GMPLOG (GL_ERROR, "Couldn't make decoded frame"); GMPLOG (GL_ERROR, "Couldn't make decoded frame");
return; return;
} }
@ -682,7 +718,7 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
GMPLOG (GL_DEBUG, "Allocated size = " GMPLOG (GL_DEBUG, "Allocated size = "
<< frame->AllocatedSize (kGMPYPlane)); << frame->AllocatedSize (kGMPYPlane));
frame->SetTimestamp (inputFrame->TimeStamp()); frame->SetTimestamp (inputFrame->TimeStamp());
frame->SetRenderTime_ms (renderTimeMs); frame->SetDuration (inputFrame->Duration());
callback_->Decoded (frame); callback_->Decoded (frame);
stats_.FrameOut(); stats_.FrameOut();
@ -690,7 +726,7 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
GMPVideoHost* host_; GMPVideoHost* host_;
GMPThread* worker_thread_; GMPThread* worker_thread_;
GMPDecoderCallback* callback_; GMPVideoDecoderCallback* callback_;
ISVCDecoder* decoder_; ISVCDecoder* decoder_;
FrameStats stats_; FrameStats stats_;
}; };

View File

@ -13,6 +13,9 @@
class gmp_args_base : public GMPTask { class gmp_args_base : public GMPTask {
public: public:
void Run() = 0; void Run() = 0;
void Destroy() {
delete this;
}
}; };
// The generated file contains four major function templates // The generated file contains four major function templates