Bug 1144523 - Convert input buffer to expected format for OpenH264 GMP plugin. r=cpearce

This commit is contained in:
Matthew Gregan 2015-03-20 17:52:10 +13:00
parent 7ce379889f
commit 49d729eb7b
7 changed files with 50 additions and 2 deletions

View File

@ -6,6 +6,7 @@
#include "GMPVideoDecoder.h"
#include "GMPVideoHost.h"
#include "mozilla/Endian.h"
#include "prsystem.h"
namespace mozilla {
@ -132,13 +133,26 @@ GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
memcpy(frame->Buffer(), aSample->data, frame->Size());
// Convert 4-byte NAL unit lengths to host-endian 4-byte buffer lengths to
// suit the GMP API.
if (mConvertNALUnitLengths) {
const int kNALLengthSize = 4;
uint8_t* buf = frame->Buffer();
while (buf < frame->Buffer() + frame->Size() - kNALLengthSize) {
uint32_t length = BigEndian::readUint32(buf) + kNALLengthSize;
*reinterpret_cast<uint32_t *>(buf) = length;
buf += length;
}
}
frame->SetBufferType(GMP_BufferLength32);
frame->SetEncodedWidth(mConfig.display_width);
frame->SetEncodedHeight(mConfig.display_height);
frame->SetTimeStamp(aSample->composition_timestamp);
frame->SetCompleteFrame(true);
frame->SetDuration(aSample->duration);
frame->SetFrameType(aSample->is_sync_point ? kGMPKeyFrame : kGMPDeltaFrame);
frame->SetBufferType(GMP_BufferLength32);
return frame;
}
@ -157,6 +171,16 @@ GMPVideoDecoder::Init()
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(mHost && mGMP);
// GMP implementations have interpreted the meaning of GMP_BufferLength32
// differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as
// specified in the GMP API, where each buffer is prefixed by a 32-bit
// host-endian buffer length that includes the size of the buffer length
// field. Other existing GMPs currently expect GMP_BufferLength32 (when
// combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to
// 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian
// and do not include the length of the buffer length field.
mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264");
GMPVideoCodec codec;
memset(&codec, 0, sizeof(codec));

View File

@ -62,6 +62,7 @@ protected:
, mGMP(nullptr)
, mHost(nullptr)
, mAdapter(aAdapter)
, mConvertNALUnitLengths(false)
{
}
@ -79,6 +80,7 @@ public:
VideoInfo(aConfig.display_width,
aConfig.display_height),
aImageContainer))
, mConvertNALUnitLengths(false)
{
}
@ -100,9 +102,9 @@ private:
GMPVideoDecoderProxy* mGMP;
GMPVideoHost* mHost;
nsAutoPtr<VideoCallbackAdapter> mAdapter;
bool mConvertNALUnitLengths;
};
} // namespace mozilla
#endif // GMPVideoDecoder_h_

View File

@ -1002,6 +1002,12 @@ GMPParent::SetNodeId(const nsACString& aNodeId)
mNodeId = aNodeId;
}
const nsCString&
GMPParent::GetDisplayName() const
{
return mDisplayName;
}
const nsCString&
GMPParent::GetVersion() const
{

View File

@ -115,6 +115,7 @@ public:
void SetNodeId(const nsACString& aNodeId);
const nsACString& GetNodeId() const { return mNodeId; }
const nsCString& GetDisplayName() const;
const nsCString& GetVersion() const;
// Returns true if a plugin can be or is being used across multiple NodeIds.

View File

@ -182,6 +182,18 @@ GMPVideoDecoderParent::Drain()
return NS_OK;
}
const nsCString&
GMPVideoDecoderParent::GetDisplayName() const
{
if (!mIsOpen) {
NS_WARNING("Trying to use an dead GMP video decoder");
}
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
return mPlugin->GetDisplayName();
}
// Note: Consider keeping ActorDestroy sync'd up when making changes here.
nsresult
GMPVideoDecoderParent::Shutdown()

View File

@ -45,6 +45,7 @@ public:
virtual nsresult Reset() MOZ_OVERRIDE;
virtual nsresult Drain() MOZ_OVERRIDE;
virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
virtual const nsCString& GetDisplayName() const MOZ_OVERRIDE;
// GMPSharedMemManager
virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) MOZ_OVERRIDE

View File

@ -49,6 +49,8 @@ public:
// Call to tell GMP/plugin the consumer will no longer use this
// interface/codec.
virtual void Close() = 0;
virtual const nsCString& GetDisplayName() const = 0;
};
#endif