Merge pull request #2023 from ethanhugg/refcount

Change GMP code to RefCount instead of deleting on enc/decode complete.
This commit is contained in:
sijchen 2015-07-09 16:28:02 +08:00
commit 703cce0214
4 changed files with 503 additions and 293 deletions

141
module/RefCounted.h Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright 2015, Mozilla Foundation and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RefCount_h__
#define __RefCount_h__
#include <stdint.h>
#include <assert.h>
extern GMPPlatformAPI* g_platform_api;
inline GMPMutex* GMPCreateMutex() {
GMPMutex* mutex;
if (!g_platform_api) {
return nullptr;
}
GMPErr err = g_platform_api->createmutex(&mutex);
assert(mutex);
return GMP_FAILED(err) ? nullptr : mutex;
}
class AutoLock {
public:
explicit AutoLock(GMPMutex* aMutex)
: mMutex(aMutex)
{
assert(aMutex);
if (mMutex) {
mMutex->Acquire();
}
}
~AutoLock() {
if (mMutex) {
mMutex->Release();
}
}
private:
GMPMutex* mMutex;
};
class AtomicRefCount {
public:
explicit AtomicRefCount(uint32_t aValue)
: mCount(aValue)
, mMutex(GMPCreateMutex())
{
assert(mMutex);
}
~AtomicRefCount()
{
if (mMutex) {
mMutex->Destroy();
}
}
uint32_t operator--() {
AutoLock lock(mMutex);
return --mCount;
}
uint32_t operator++() {
AutoLock lock(mMutex);
return ++mCount;
}
operator uint32_t() {
AutoLock lock(mMutex);
return mCount;
}
private:
uint32_t mCount;
GMPMutex* mMutex;
};
// Note: Thread safe.
class RefCounted {
public:
void AddRef() {
++mRefCount;
}
uint32_t Release() {
uint32_t newCount = --mRefCount;
if (!newCount) {
delete this;
}
return newCount;
}
protected:
RefCounted()
: mRefCount(0)
{
}
virtual ~RefCounted()
{
assert(!mRefCount);
}
AtomicRefCount mRefCount;
};
template<class T>
class RefPtr {
public:
explicit RefPtr(T* aPtr) : mPtr(nullptr) {
Assign(aPtr);
}
~RefPtr() {
Assign(nullptr);
}
T* operator->() const { return mPtr; }
RefPtr& operator=(T* aVal) {
Assign(aVal);
return *this;
}
private:
void Assign(T* aPtr) {
if (mPtr) {
mPtr->Release();
}
mPtr = aPtr;
if (mPtr) {
aPtr->AddRef();
}
}
T* mPtr;
};
#endif // __RefCount_h__

View File

@ -53,8 +53,6 @@
#include "codec_app_def.h"
#include "codec_api.h"
#include "task_utils.h"
#if defined(_MSC_VER)
#define PUBLIC_FUNC __declspec(dllexport)
#else
@ -91,6 +89,8 @@
# define nullptr __null
#endif
#include "task_utils.h"
static int g_log_level = 0;
#define GMPLOG(l, x) do { \
@ -116,7 +116,7 @@ const char* kLogStrings[] = {
};
static GMPPlatformAPI* g_platform_api = nullptr;
GMPPlatformAPI* g_platform_api = nullptr;
class OpenH264VideoEncoder;
@ -179,7 +179,7 @@ class FrameStats {
const std::string type_;
};
class OpenH264VideoEncoder : public GMPVideoEncoder {
class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
public:
OpenH264VideoEncoder (GMPVideoHost* hostAPI) :
host_ (hostAPI),
@ -187,11 +187,9 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
encoder_ (nullptr),
max_payload_size_ (0),
callback_ (nullptr),
stats_ ("Encoder") {}
virtual ~OpenH264VideoEncoder() {
worker_thread_->Join();
}
stats_ ("Encoder") {
AddRef();
}
virtual void InitEncode (const GMPVideoCodec& codecSettings,
const uint8_t* aCodecSpecific,
@ -285,7 +283,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
assert (aFrameTypesLength != 0);
worker_thread_->Post (WrapTask (
worker_thread_->Post (WrapTaskRefCounted (
this, &OpenH264VideoEncoder::Encode_w,
inputImage,
(aFrameTypes)[0]));
@ -363,10 +361,14 @@ class OpenH264VideoEncoder : public GMPVideoEncoder {
}
virtual void EncodingComplete() {
delete this;
Release();
}
private:
virtual ~OpenH264VideoEncoder() {
worker_thread_->Join();
}
void Error (GMPErr error) {
if (callback_) {
callback_->Error (error);
@ -560,17 +562,16 @@ void copyWithStartCode(std::vector<uint8_t>& out, const uint8_t* in, size_t size
out.insert(out.end(), in, in + size);
}
class OpenH264VideoDecoder : public GMPVideoDecoder {
class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
public:
OpenH264VideoDecoder (GMPVideoHost* hostAPI) :
host_ (hostAPI),
worker_thread_ (nullptr),
callback_ (nullptr),
decoder_ (nullptr),
stats_ ("Decoder") {}
virtual ~OpenH264VideoDecoder() {
}
stats_ ("Decoder") {
AddRef();
}
virtual void InitDecode (const GMPVideoCodec& codecSettings,
const uint8_t* aCodecSpecific,
@ -691,7 +692,7 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
break;
}
DECODING_STATE dState = dsErrorFree;
worker_thread_->Post (WrapTask (
worker_thread_->Post (WrapTaskRefCounted (
this, &OpenH264VideoDecoder::Decode_w,
inputFrame,
missingFrames,
@ -715,10 +716,13 @@ class OpenH264VideoDecoder : public GMPVideoDecoder {
}
virtual void DecodingComplete() {
delete this;
Release();
}
private:
virtual ~OpenH264VideoDecoder() {
}
void Error (GMPErr error) {
if (callback_) {
callback_->Error (error);

View File

@ -7,6 +7,29 @@ boilerplate = "/* This Source Code Form is subject to the terms of the Mozilla P
* License, v. 2.0. If a copy of the MPL was not distributed with this\n\
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n"
includes = "#include \"RefCounted.h\"\n"
refcountclass = "class RefCountTaskWrapper : public gmp_args_base {\n\
public:\n\
RefCountTaskWrapper(GMPTask* aTask, RefCounted* aRefCounted)\n\
: mTask(aTask)\n\
, mRefCounted(aRefCounted)\n\
{}\n\
virtual void Run() {\n\
mTask->Run();\n\
}\n\
virtual void Destroy() {\n\
mTask->Destroy();\n\
gmp_args_base::Destroy();\n\
}\n\
private:\n\
~RefCountTaskWrapper() {}\n\
\n\
GMPTask* mTask;\n\
RefPtr<RefCounted> mRefCounted;\n\
};\n"
def gen_args_type(args, member):
if member:
ret = ["C o"]
@ -35,16 +58,16 @@ def gen_args_(args):
def gen_init(args, r = False, member = False):
if member:
ret = ["o_(o)"]
ret = ["o_ (o)"]
else:
ret = []
ret.append("m_(m)")
ret.append("m_ (m)")
if r:
ret.append("r_(r)")
ret.append("r_ (r)")
for arg in range(0, args):
ret.append("a%d_(a%d)"%(arg, arg))
ret.append("a%d_ (a%d)"%(arg, arg))
return ", ".join(ret)
def gen_typenames(args, member):
@ -84,12 +107,12 @@ def generate_class_template(args, ret = False, member = True):
print " public:"
if not ret:
print " gmp_args_%s_%d("%(nm, args) + gen_args_type(args, member) + ") :"
print " gmp_args_%s_%d ("%(nm, args) + gen_args_type(args, member) + ") :"
print " " + gen_init(args, False, member) + " {}"
else:
print " gmp_args_%s_%d_ret("%(nm, args) + gen_args_type(args, member) + ", R *r) :"
print " gmp_args_%s_%d_ret ("%(nm, args) + gen_args_type(args, member) + ", R* r) :"
print " " + gen_init(args, True, member) + " {}"
print " virtual bool returns_value() const { return true; }"
print " virtual bool returns_value() const {\n return true;\n }"
print
print " void Run() {"
if ret:
@ -97,9 +120,9 @@ def generate_class_template(args, ret = False, member = True):
else:
print " ",
if member:
print "((*o_).*m_)(" + gen_args_(args) + ");"
print "((*o_).*m_) (" + gen_args_(args) + ");"
else:
print "m_(" + gen_args_(args) + ");"
print "m_ (" + gen_args_(args) + ");"
print " }"
print
print " private:"
@ -125,11 +148,19 @@ def generate_function_template(args, member):
print "// %d arguments --"%args
print "template<" + gen_typenames(args, member) + ">"
print "gmp_args_%s_%d<"%(nm, args) + gen_types(args, member) + ">* WrapTask%s("%NM + gen_args_type(args, member) + ") {"
print "gmp_args_%s_%d<"%(nm, args) + gen_types(args, member) + ">* WrapTask%s ("%NM + gen_args_type(args, member) + ") {"
print " return new gmp_args_%s_%d<"%(nm, args) + gen_types(args, member) + ">"
print " (" + gen_args(args, member) + ");"
print "}"
print
if member:
print "template<" + gen_typenames(args, member) + ">"
print "GMPTask*"
print "WrapTaskRefCounted%s ("%NM + gen_args_type(args, member) + ") {"
print " GMPTask *t = WrapTask%s ("%NM + gen_args(args, member) + ");"
print " return new RefCountTaskWrapper(t, o);"
print "}"
print
def generate_function_template_ret(args, member):
if member:
@ -140,15 +171,20 @@ def generate_function_template_ret(args, member):
NM = "NM";
print "// %d arguments --"%args
print "template<" + gen_typenames(args, member) + ", typename R>"
print "gmp_args_%s_%d_ret<"%(nm, args) + gen_types(args, member) + ", R>* WrapTask%sRet("%NM + gen_args_type(args, member) + ", R* r) {"
print "gmp_args_%s_%d_ret<"%(nm, args) + gen_types(args, member) + ", R>* WrapTask%sRet ("%NM + gen_args_type(args, member) + ", R* r) {"
print " return new gmp_args_%s_%d_ret<"%(nm, args) + gen_types(args, member) + ", R>"
print " (" + gen_args(args, member) + ", r);"
print "}"
print
print boilerplate
print
print includes
print
print refcountclass
print
for num_args in range (0, MAX_ARGS):
generate_class_template(num_args, False, False)

File diff suppressed because it is too large Load Diff